文章目錄
python中使用subprocess.Popen傳回值亂碼解決方案
By 馬冬亮(凝霜 Loki)
一個人的戰爭(http://blog.csdn.net/MDL13412)
問題描述
在python 2.7中,使用subprocess.Popen()調用*nix命令,並通過管道,擷取其輸出,並將其傳回值格式化成utf-8格式,但是對於傳回值出現中文時,會造成轉碼錯誤,具體情況如下:
# -*- coding: utf-8 -*-import subprocessMY_RPM_FILE_PATH = '/home/dongliang.ma/rpmbuild/RPMS/noarch/q-yumtools-server-1.1.0-1.el6.noarch.rpm'try: cmd_args = ['rpm', '-qip', MY_RPM_FILE_PATH] infos = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, shell=False).stdout.readlines() unicode_text = u''.join(infos) print unicode_textexcept Exception, _ex: print 'ERROR: %s' % str(_ex)
程式輸出如下:
問題分析
從python的報錯來看,是中文編碼超出了ASCII碼的表示範圍,具體報錯的代碼為:
unicode_text = u''.join(infos)
既然是無法表示,我的第一反應就是進行轉碼,於是將代碼改寫:
# -*- coding: utf-8 -*-import subprocessMY_RPM_FILE_PATH = '/home/dongliang.ma/rpmbuild/RPMS/noarch/q-yumtools-server-1.1.0-1.el6.noarch.rpm'try: cmd_args = ['rpm', '-qip', MY_RPM_FILE_PATH] infos = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, shell=False).stdout.readlines() unicode_text = u'' for line in infos: unicode_text = unicode_text + line.encode('utf-8') print unicode_textexcept Exception, _ex: print 'ERROR: %s' % str(_ex)
但是經過轉換後,代碼運行報錯和先前一樣,經過分析,在執行下面代碼時,問題就已經發生:
infos = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, shell=False).stdout.readlines()
那麼現在問題就定位到如何讓infos這個變數能夠儲存中文,經過查閱文檔,發現python有一個defaultencoding的概念,即預設使用的編碼,只要將這個屬性設定為utf-8,那麼就可以正確儲存中文,其具體設定方法是使用:
reload(sys)sys.setdefaultencoding('utf-8')
經過上述設定後,即可正確處理中文資訊。
最終方案
# -*- coding: utf-8 -*-import sysimport subprocessMY_RPM_FILE_PATH = '/home/dongliang.ma/rpmbuild/RPMS/noarch/q-yumtools-server-1.1.0-1.el6.noarch.rpm'try: reload(sys) sys.setdefaultencoding('utf-8') cmd_args = ['rpm', '-qip', MY_RPM_FILE_PATH] infos = subprocess.Popen(cmd_args, stdout=subprocess.PIPE, shell=False).stdout.readlines() unicode_text = u''.join(infos) print unicode_textexcept Exception, _ex: print 'ERROR: %s' % str(_ex)
運行結果:
總結
- python預設使用的編碼是ASCII,這會導致國際化的問題,一個比較好的做法是,在程式運行時,將預設編碼修改為utf-8;
- 在python源檔案中使用unicode字元時,一定要將python檔案儲存為utf-8格式,而不是僅僅在開頭加上# -*- coding: utf-8 -*-這個bug,導致我調試發送郵件時浪費了不少時間。