質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

ただいまの
回答率

88.80%

Pythonのtelnetlibで情報取得し、ファイルに書き出すと改行が余分にできてしまう

解決済

回答 2

投稿 編集

  • 評価
  • クリップ 0
  • VIEW 128

gcrest

score 1

前提・実現したいこと

pythonのtelnetlibを使用してCiscoのCSR1000vからshow runを取得しようとしているのですが、windows10で実行すると下記出力結果のように改行が一つ余分にできてしまいます。余分な改行をなくすにはどうすればよいでしょうか。

改行が余分に含まれる出力ファイルの一部

以下、出力されたファイルの一部。

show running-config

Building configuration...

Current configuration : 1108 bytes

!

! Last configuration change at 23:03:32 UTC Sat Oct 17 2020

!

version 15.4

service timestamps debug datetime msec

service timestamps log datetime msec

no platform punt-keepalive disable-kernel-core

platform console virtual

!

使用したソースコード

# coding:utf-8

import telnetlib

def main():
    result = telnet("x.x.x.x")
    writeFile("x.x.x.x", result)

def writeFile(client, text):
    with open("test" + '.txt', mode='w') as wf:
        wf.writelines(text)
    wf.close()

def telnet(clientIp):
    tn = telnetlib.Telnet(clientIp)

    tn.read_until(b'Username:')
    tn.write(b'cisco' + b'\n')

    tn.read_until(b'Password:')
    tn.write(b'cisco' + b'\n')
    tn.read_until(b'>')

    tn.write(b'enable' + b'\n')

    tn.read_until(b'Password:')
    tn.write(b'cisco' + b'\n')

    tn.read_until(b'#')
    tn.write(b'terminal length 0' + b'\n')
    tn.write(b'show running-config' + b'\n')

    tn.read_until(b'#')

    result = tn.read_until(b"FIN\n", timeout = 1).decode('ascii', errors="replace")
    return result

    tn.close()

if __name__ == '__main__':
    main()

試したこと

WindowsのWSL(Ubuntu)で上記コードを実行し、出力されたファイルの改行はwindows側でみても、WSL上でcatでみても正常な改行のファイルが出力されます。

利用環境

windows 10
python 3.6.3
csr1000v IOS XE 03.11.04.S

  • 気になる質問をクリップする

    クリップした質問は、後からいつでもマイページで確認できます。

    またクリップした質問に回答があった際、通知やメールを受け取ることができます。

    クリップを取り消します

  • 良い質問の評価を上げる

    以下のような質問は評価を上げましょう

    • 質問内容が明確
    • 自分も答えを知りたい
    • 質問者以外のユーザにも役立つ

    評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。

    質問の評価を上げたことを取り消します

  • 評価を下げられる数の上限に達しました

    評価を下げることができません

    • 1日5回まで評価を下げられます
    • 1日に1ユーザに対して2回まで評価を下げられます

    質問の評価を下げる

    teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。

    • プログラミングに関係のない質問
    • やってほしいことだけを記載した丸投げの質問
    • 問題・課題が含まれていない質問
    • 意図的に内容が抹消された質問
    • 過去に投稿した質問と同じ内容の質問
    • 広告と受け取られるような投稿

    評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正、ベストアンサー選択の依頼

  • otn

    2020/10/18 09:22

    > windows10で実行すると下記出力結果のように改行が一つ余分にできてしまいます。
    と、
    > WindowsのWSL(Ubuntu)で上記コードを実行し、出力されたファイルの改行はwindows側でみても、WSL上でcatでみても正常な改行のファイルが出力されます。

    の関係が分かりません。
    どういう確認の仕方をしたらどうだったのかを具体的に書いてください。

    キャンセル

  • gcrest

    2020/10/18 11:14 編集

    コメントいただきありがとうございます。

    toast-uzさん
    >生のWindows10で問題が出て、WSL上では問題が出ていない、という理解でよいでしょうか?
     →そうです。
    >「改行が余分に含まれる出力ファイル」は、どうやって出力結果を見たのでしょうか?メモ帳?
     →windows標準のメモ帳、sublimetextで確認しました。
      WSL上でpythonコードを実行して得たファイルはWSL(Ubuntu)上のcatコマンドでも、windows上のメモ帳、sublimetextでも余分な改行がなく正常に表示されています。

    otnさん
    >どういう確認の仕方をしたらどうだったのかを具体的に書いてください。
     →windows10での実行はエクスプローラでpythonコードをダブルクリックして実行しています。出力ファイルの確認はWindows付属のメモ帳、Sublimetextで余分な改行が含まれることを確認しました。
      WSL(Ubuntu)上での実行はコマンドプロンプト上でbashコマンドでWSLに入り、「python ファイル名」で実行しています。出力ファイルの確認はWSL上でのcatコマンド、windows付属のメモ帳、sublimetextで余分な改行が含まれないことを確認しました。
      補足ですが、WSL上で作成したファイルはWindows側で確認することができ、Windows側で作成したファイルもWSL上で確認できます。

    キャンセル

  • dodox86

    2020/10/18 11:19

    > result = tn.read_until(b"FIN\n", timeout = 1).decode('ascii', errors="replace")
    のresultの時点で、バイナリレベルでresultの値がどうなっているか確認してみたらどうでしょうか。telnetサーバー間との通信の生データあるいはライブラリの扱いで、改行コード(CRやLF)がどのようになってしまっているか確認した方が良いと思います。現状ではどこで改行が余分に付与されてしまっているか不確かです。

    キャンセル

回答 2

checkベストアンサー

+1

質問者様に確認中の部分はありますが、概ねこれが回答だろうという目星はつけましたので、回答します。

with open("test" + '.txt', mode='w') as wf:

with open("test" + '.txt', mode='w', newline='\n') as wf:
に書き換えてみてください。

Windowsは(文字コードに加え)改行コードの扱いが異なるため、テキストファイルの読み書きには非互換が発生します。上記コードの変更により、改行コードの扱いをLinux系とあわせることが可能です。
参考: Windows上で実行したPythonの出力ファイルの改行コードが変わる

ただし、この改行コードの扱いはWindowsネイティブのものですので、メモ帳等のツールで出力ファイルを参照した場合に、改行が二重に見えてしまう、というのは不思議です。質問者様に確認の方法をお聞きしているのは、そのためです。
(Windows仕様で出力したテキストファイルを、macのメモ帳的アプリで見ると、改行が二重に見えます。一方、macのターミナルでcatで見ると、二重には見えません。各ツールがWindows仕様の改行に対応しているかどうかで、見え方が異なります。)

投稿

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/18 11:35

    ありがとうございます!解決しました!

    コメントで頂いた通りにコードを書き換えたところ改行が正常に表示できることが確認できました。

    dodox86さんにアドバイス頂いた通りにバイナリで確認したところ、修正したコードの出力結果と修正前の出力結果で改行コードの部分に違いがありました。
     修正前:0d 0d 0a
     修正後:0d 0a
    参考にWSL上でhexdumpを取得した一部を載せます。

    修正後の出力結果のhexdump
    --------------------------------------------------
    $ hexdump -C test.txt
    00000000 0d 0a 0d 0a 55 73 65 72 20 41 63 63 65 73 73 20 |....User Access |
    00000010 56 65 72 69 66 69 63 61 74 69 6f 6e 0d 0a 0d 0a |Verification....|
    00000020 55 73 65 72 6e 61 6d 65 3a 20 63 69 73 63 6f 0d |Username: cisco.|
    00000030 0a 50 61 73 73 77 6f 72 64 3a 20 0d 0a 63 73 72 |.Password: ..csr|

    修正前の出力結果のhexdump
    --------------------------------------------------
    $ hexdump -C test.txt
    00000000 0d 0d 0a 0d 0d 0a 55 73 65 72 20 41 63 63 65 73 |......User Acces|
    00000010 73 20 56 65 72 69 66 69 63 61 74 69 6f 6e 0d 0d |s Verification..|
    00000020 0a 0d 0d 0a 55 73 65 72 6e 61 6d 65 3a 20 63 69 |....Username: ci|
    00000030 73 63 6f 0d 0d 0a 50 61 73 73 77 6f 72 64 3a 20 |sco...Password: |
    00000040 0d 0d 0a 63 73 72 31 3e 65 6e 61 62 6c 65 0d 0d |...csr1>enable..|
    00000050 0a 50 61 73 73 77 6f 72 64 3a 20 0d 0d 0a 63 73 |.Password: ...cs|
    00000060 72 31 23 74 65 72 6d 69 6e 61 6c 20 6c 65 6e 67 |r1#terminal leng|

    キャンセル

  • 2020/10/18 12:39

    よくわかりました。もう少し原理的に対策がわかりましたが、ベストをいただきましたので、別解として回答追加します。

    キャンセル

+1

質問者様とのやりとりで、本質的なところがもっとわかりました。既にベストをいただいたので、別解とします。

def telnet(clientIp):
return resultの前に
result = result.replace('\r\n', '\n')

と入れて、ファイル書き込みのところは元のままにするとよいでしょう。

理由

  • telnetの電文は仕様により、改行はCR+LFで表されます。
    参考: telnetがテキストデータを送る際の改行コードは、windowsだろうが、Mac、Linuxだろうが、 常にNVT ASCIIの改行コード(CR+LF:0x0D0A)です
  • telnetlibは、そのCRLFをそのまま結果として返す仕様のようです。よって、resultの中の改行はCR+LFとなっています。
  • ところが、本来、プログラム中の改行コードはLF('\n')のみです。よってCRは改行ではなく単独の文字としてみなされます。
  • Linux仕様のテキストファイルは改行コードはLFなので、CRはそのまま、LFもそのまま出力します。結果としてCR+LFが改行位置に入ります。
  • しかしWindows仕様のテキストファイルは改行コードはCR+LFなので、CRはそのまま、LFはCR+LFとして出力します。結果としてCR+CR+LFが改行位置に入ります。
  • 最近のエディタは優秀なので、Linux・Windowsのテキストファイルを自動判別して自然に見せるようになっていて、CRであろうがLFであろうがCR+LFであろうが1回の改行として判別します。ところが、CR+CR+LFは想定外で、CR+(CR+LF)の2つの改行として判別してしまいます。これが質問者様に発生した状況です。
  • 上記の対策としてLinuxの改行仕様でテキストファイルを書き込みするようにしていただきました。しかし、本質的にはプログラム中でCR+LFを改行コードに持つ文字列を処理するところから修正が必要です。そのため、telnet終了後に得られた文字列の改行コードを一括変換する、という今回の対策をオススメします。これにより、プログラム中では、正しい文字列として処理でき、なおかつテキストファイル出力は、環境にあわせてできるようになります。

投稿

編集

  • 回答の評価を上げる

    以下のような回答は評価を上げましょう

    • 正しい回答
    • わかりやすい回答
    • ためになる回答

    評価が高い回答ほどページの上位に表示されます。

  • 回答の評価を下げる

    下記のような回答は推奨されていません。

    • 間違っている回答
    • 質問の回答になっていない投稿
    • スパムや攻撃的な表現を用いた投稿

    評価を下げる際はその理由を明確に伝え、適切な回答に修正してもらいましょう。

  • 2020/10/18 21:57

    詳細に説明いただきありがとうございます。

    return resultの前に下記コードを入れた場合にも、問題なく改行が表示され、hexdumpで見てもWindowsでは改行が\r\nとなり、WSLで実行すると\nになることが確認できました。

    result = result.replace('\r\n', '\n')

    もともとtelnetlibで取得した文字列の改行コードが\r\nであることが問題であるみたいなので、Telnet取得後に文字列の改行コードを変換するようにします。

    ありがとうございました。理解が深まりました。

    キャンセル

15分調べてもわからないことは、teratailで質問しよう!

  • ただいまの回答率 88.80%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る