2012-04-03 46 views
3

我正在Windows PowerShell中運行我的Python腳本,並且該腳本應該使用Popen運行另一個程序,然後管理該程序的輸出(實際上是Mercurial)以用於腳本。當我嘗試在PowerShell中執行腳本時,出現編碼錯誤。Python Popen未能在Windows PowerShell中使用正確的編碼

我很確定它正在發生,因爲在獲取Popen調用的輸出時,Python沒有使用PowerShell正在使用的正確編碼。 問題是我不知道如何告訴Python使用正確的編碼。


我的腳本看起來像

# -*- coding: utf-8 -*- 
#... some imports 
proc = Popen(["hg", "--cwd", self.path, "--encoding", "UTF-8"] + list(args), stdout=PIPE, stderr=PIPE) 
#... other code 

當我在Linux上運行此腳本時,我沒有任何問題。我也可以使用PowerShell在Windows 7 Home Premium 64位中運行腳本,而不會出現任何問題。此Windows 7中的PowerShell正在使用代碼頁850,也就是chcp的輸出爲850(「ibm850」)。

然而,當我使用具有默認的編碼CP437(chcp = 437)一個PowerShell運行在一個Windows 7的入門32位腳本,我在Python(2.7版出現以下錯誤。 2):

File "D:\Path\to\myscript.py", line 55, in hg_command 
    proc = Popen(["hg", "--cwd", self.path, "--encoding", "UTF-8"] + list(args), stdout=PIPE, stderr=PIPE) 
File "C:\Program files\Python27\lib\subprocess.py", line 679, in __init__ 
    errread, errwrite) 
File "C:\Program files\Python27\lib\subprocess.py", line 852, in _execute_child 
    args = list2cmdline(args) 
File "C:\Program files\Python27\lib\subprocess.py", line 615, in list2cmdline 
    return ''.join(result) 
UnicodeDecodeError: 'utf8' codec cant decode byte 0xe3 in position 0: unexpected end of data 

我曾嘗試以下,沒有成功(即,上述錯誤報告保持不變):

  • 刪除線# -*- coding: utf-8 -*-從我的腳本。
  • 刪除在我的腳本中通過Popen運行Mercurial的-- encoding UTF-8選項。
  • 在執行我的腳本之前,在PowerShell中將編碼更改爲chcp 850
  • 我在其他堆棧溢出答案中發現了很多其他的Python黑客入侵。

對於我的具體細節,我的整個源代碼可用here in BitBuckethgapi.py是提供錯誤的腳本。


UPDATE: 腳本是由該other script,這是設置編碼這樣

sys.setdefaultencoding("utf-8") 

這行看起來很重要,因爲如果我註釋掉,我得到了一個名爲不同的錯誤:

UnicodeDecoreError: 'ascii' codec cant decode byte 0xe3 in position 0: ordinal not in range(128) 
+0

當使用[mercurial api](http://mercurial.selenic.com/wiki/MercurialApi)時,你有同樣的問題嗎?既然你使用python,它看起來很自然。 – 2012-04-03 12:30:37

+1

該項目用於使用mercurial內部API,但我切換到命令行API,因爲這是官方穩定的。除了擴展名外,不應該使用內部API。 – 2012-04-03 12:41:15

+0

這看起來更像是一個'args'數組的問題,因爲異常在'list2cmdline'中引發。也許'args'或'self.path'是一個字節串而不是一個Unicode字符串? – Philipp 2012-04-03 23:13:21

回答

1

使用from __future__ import unicode_literals後,我開始了同樣的錯誤,但在代碼的不同部分:

out, err = [x.decode("utf-8") for x in proc.communicate()] 

給了錯誤

UnicodeDecodeError: 'utf8' codec cant decode byte 0xe3 in position 33 .... 

事實上,x字節串\xe3 (包括cp1252中的ã)。所以,而不是使用x.decode('utf-8'),我使用x.decode('windows-1252'),並沒有給我沒有錯誤。爲了支持任何類型的編碼,我最終使用了x.decode(sys.stdout.encoding)問題已解決。

這是在Python 3.2.2與Windows 7 Starter電腦,但在同一臺計算機上的Python 2.7也正常工作。

+0

有趣的 - 在我的情況下http://stackoverflow.com/questions/28101187/deal-with-unicode-usernames-in-python-mkdtemp'sys.stdout.encoding'是無 - 會locale.getpreferredencoding()做的伎倆? – 2015-01-23 15:11:51

2

嘗試將編碼更改爲cp1252。 Windows中的Popen需要編碼爲cp1252的shell命令。這看起來像一個錯誤,並且它在Python 3中似乎也得到了修復。通過subprocess模塊X:http://docs.python.org/library/subprocess.html

import subprocess 
subprocess.Popen(["hg", "--cwd", self.path, "--encoding", "UTF-8"] + list(args), stdout=PIPE, stderr=PIPE) 

更新:

你的問題,也許可以通過Django的模塊smart_str功能來解決。

使用此代碼:

from django.utils.encoding import smart_str, smart_unicode 
# the cmd should contain sthe string with the commsnd that you want to execute 
smart_cmd = smart_str(cmd) 
subprocess.Popen(smart_cmd) 

你可以找到關於如何在Windows here安裝Django信息。 你可以先安裝pip,然後你可以通過啓動 具有管理員權限的命令外殼安裝Django並運行此命令:

pip install Django 

這將在你的Python安裝的site-packages目錄安裝Django。

+0

通過什麼將編碼更改爲cp1252? PowerShell中的'chcp 1252'沒有幫助。 – 2012-04-03 12:09:35

+0

它會產生相同的錯誤嗎? – 2012-04-03 12:28:08

+0

@STALTZ嘗試'$ OutputEncoding = [控制檯] :: OutputEncoding' – 2012-04-03 12:36:24

相關問題