web-dev-qa-db-ja.com

Python popen()-communication(str.encode(encoding = "utf-8"、errors = "ignore"))がクラッシュする

WindowsでPython 3.4.3を使用します。

私のスクリプトは、コンソールで少しJava=プログラムを実行し、出力を取得する必要があります。

import subprocess
p1 = subprocess.Popen([ ... ], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True)
out, err = p1.communicate(str.encode("utf-8"))

これは正常につながります

'UnicodeDecodeError:' charmap 'codec ca n't decode byte 0x9d in position 135:character maps to <undefined>'.

今私はエラーを無視したいです:

out, err = p1.communicate(str.encode(encoding="utf-8", errors="ignore"))

これは私がグーグルを使用するための助けを見つけなかったより興味深いエラーにつながります:

TypeError: 'str'オブジェクトの記述子 'encode'には引数が必要です

したがって、pythonはstr.encode(...)の引数が何であるかさえ知らないようです。エラーの部分を省略した場合も同様です。

10
user136036

_universal_newlines=True_はテキストモードを有効にします。 _stdout=PIPE_と組み合わせると、Windowsではutf-8ではないlocale.getpreferredencoding(False)を使用して子プロセスの出力が強制的にデコードされます。そのため、UnicodeDecodeErrorが表示されます。

Utf-8エンコーディングを使用してサブプロセスの出力を読み取るには、_universal_newlines=True_をドロップします。

_#!/usr/bin/env python3
from subprocess import Popen, PIPE

with Popen(r'C:\path\to\program.exe "arg 1" "arg 2"',
           stdout=PIPE, stderr=PIPE) as p:
    output, errors = p.communicate()
lines = output.decode('utf-8').splitlines()
_

str.encode("utf-8")"utf-8".encode()と同等です。 _stdin=PIPE_を設定し、子プロセスが_b'utf-8'_バイト文字列を入力として期待しない限り、それを.communicate()に渡す意味はありません。

str.encode(encoding="utf-8", errors="ignore)の形式はklass.method(**kwargs)です。 .encode()メソッドはself(文字列オブジェクト)を想定しているため、TypeErrorが表示されます。

_>>> str.encode("abc", encoding="utf-8", errors="ignore") #XXX don't do it
b'abc'
>>> "abc".encode(encoding="utf-8", errors="ignore")
b'abc'
_

正当な理由がない限り、klass.method(obj)の代わりにobj.method()を使用しないでください。

16
jfs

クラス自体で.encode()を呼び出すことは想定されていません。あなたがおそらくやりたいことは次のようなものです

_p1.communicate("FOOBAR".encode("utf-8"))
_

表示されているエラーメッセージは、インスタンスではなくクラスで呼び出したため、encode()関数にはエンコードするものが何もないことを意味します(selfとして渡されます) encode())へのパラメーター。

2
cemper93