LinuxのWordカウントユーティリティwcを実行して、/ var/log/syslogの現在の行数を確認したいので、増加していることを検出できます。さまざまなテストを試しましたが、wcから結果を取得している間に、行数とコマンド(たとえば、var/log/syslog)の両方が含まれています。
1338/var/log/syslogが返されますが、行数だけが必要なので、/ var/log/syslogの部分を取り除き、1338だけを保持します。
私はそれをバイト文字列から文字列に変換し、結果を削除しようとしましたが、喜びはありませんでした。文字列への変換、ストリッピング、デコードなどの同じ話-すべてが私が探している出力を生成できません。
これらは、syslogの1338行で得られるもののいくつかの例です。
以下に、このナットをクラックしようとするために作成したテストコードを示しますが、解決策はありません。
import subprocess
#check_output returns byte string
stdoutdata = subprocess.check_output("wc --lines /var/log/syslog", Shell=True)
print("2A stdoutdata: " + str(stdoutdata))
stdoutdata = stdoutdata.decode("utf-8")
print("2B stdoutdata: " + str(stdoutdata))
stdoutdata=stdoutdata.strip()
print("2C stdoutdata: " + str(stdoutdata))
これからの出力は次のとおりです。
2A stdoutdata:b'1338/var/log/syslog\n '
2B stdoutdata:1338/var/log/syslog
2C stdoutdata:1338/var/log/syslog
2D stdoutdata:1338/var/log/syslog
subprocess.getoutput()
を使用して、希望どおりに実行することをお勧めします。シェルでコマンドを実行し、 string output ( byte string =出力)。次に、 空白で分割 を実行し、返された文字列のリストから最初の要素を取得します。
これを試して:
import subprocess
stdoutdata = subprocess.getoutput("wc --lines /var/log/syslog")
print("stdoutdata: " + stdoutdata.split()[0])
* nixでシェルを呼び出して任意のバイトシーケンス('\0'
を除く)である可能性のあるファイル名をデコードしないようにするには、ファイルをstdinとして渡すことができます。
import subprocess
with open(b'/var/log/syslog', 'rb') as file:
nlines = int(subprocess.check_output(['wc', '-l'], stdin=file))
print(nlines)
または、デコードエラーを無視することもできます。
import subprocess
stdoutdata = subprocess.check_output(['wc', '-l', '/var/log/syslog'])
nlines = int(stdoutdata.decode('ascii', 'ignore').partition(' ')[0])
print(nlines)
Python 3.6なので、check_output()
にencodingを与えることで、str
の代わりにbytes
を返すことができます。パラメータ:
_check_output('wc --lines /var/log/syslog', encoding='UTF-8')
_
ただし、カウントが必要なだけで、split()
とint()
の両方がbytes
で使用できるため、エンコードに煩わされる必要はありません。
_linecount = int(check_output('wc -l /var/log/syslog').split()[0])
_
外部プログラムを使用すると簡単になる場合がありますが(たとえば、journalctl
によって出力されるログ行エントリをカウントする場合)、この特定の場合、外部プログラムを使用する必要はありません。最も単純なPythonのみのソリューションは次のとおりです。
_with open('/var/log/syslog', 'rt') as f:
linecount = len(f.readlines())
_
これには、ファイル全体をメモリに読み込むという欠点があります。巨大なファイルの場合は、ファイルを開く前に_linecount = 0
_を初期化し、readlines()
の代わりに_for line in f: linecount += 1
_ループを使用して、カウント時にファイルのごく一部のみをメモリに格納します。
Curt J. Sampsonの答えもこれと同じです(文字列を返します)。
subprocess.check_output('wc -l /path/to/your/file | cut -d " " -f1', universal_newlines=True, Shell=True)
ドキュメントから:
エンコードまたはエラーが指定されている場合、またはテキストがtrueの場合、stdin、stdout、およびstderrのファイルオブジェクトは、指定されたエンコードおよびエラーまたはio.TextIOWrapperのデフォルトを使用してテキストモードで開かれます。 universal_newlines引数はtextと同等であり、後方互換性のために提供されています。デフォルトでは、ファイルオブジェクトはバイナリモードで開かれます。
似たようなものですが、subprocess.run()を使用するともう少し複雑になります。
subprocess.run(command, Shell=True, check=True, universal_newlines=True, stdout=subprocess.PIPE).stdout
subprocess.check_output()はsubprocess.run()と同等である可能性があるため。