2015-10-22 17 views
3

在Windows上使用Python 3.4.3。Python popen() - 溝通(str.encode(encoding =「utf-8」,errors =「ignore」))崩潰

我的腳本運行在控制檯中的小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 can't decode byte 0x9d in position 135: character maps to < undefined>'.

現在我想忽略錯誤:

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

這導致了一個更有趣的錯誤,我發現沒有幫助使用谷歌:

TypeError: descriptor 'encode' of 'str' object needs an argument

因此,似乎python甚至不知道str.encode(...)的參數是什麼。當你忽略錯誤部分時也是如此。

回答

7

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()。沒有意義將它傳遞給.communicate(),除非您設置了stdin=PIPE,並且子進程需要b'utf-8' bytestring作爲輸入。具有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()沒有一個很好的理由。

0

你不應該在課堂上給.encode()打電話。你可能想要做的是一樣的東西

p1.communicate("FOOBAR".encode("utf-8")) 

你得到手段的encode()功能無關的編碼,因爲你把它稱爲的類,而不是一個實例的錯誤信息(這將隨後作爲self參數傳遞給encode())。

+0

問題是:如果你使用通信(str.encode(「utf-8」)),這工作正常(可以看到幾個stackoverflow的例子),除了一些unicode錯誤。但是,當您添加錯誤參數或使用encoding =「utf-8」時,它會中斷。否則,它工作正常。 – user136036

+1

這是因爲'std.encode(「utf-8」)'的確和''utf-8「.encode()相同,它會返回...」utf-8「:)所以你實際上發送文本「utf-8」到您的應用程序 - 我不認爲這就是您想要做的。 – viraptor