https://blog.csdn.net/weiliu0626/article/details/8296282
https://blog.csdn.net/weixin_34198583/article/details/93631868
查看系統編碼
報錯的字符是一個Unicode字符,查了下發現是python3,只有str和Unicode兩種編碼,去查了python3的系統編碼:
>>> import sys >>> sys.getdefaultencoding() 'utf-8'
系統編碼就是utf8, 所以再去設置什么系統編碼,文件開頭加上‘# coding=utf8’ 對我的問題是沒啥幫助;
查看輸入輸出編碼
既然不是系統編碼,而且前面輸出都沒有問題,所以可能也不是之前讀寫文件的編碼錯誤,可能是print的時候,也就是標准輸入輸出的時候編碼問題了;那么print的時候做了什么,用的是什么編碼呢?
我們已經知道在python3中,輸出的時候,會把str/Unicode 變成utf8的編碼;來看一下環境中的輸出編碼是什么:
>>> import sys >>> sys.stdout.encoding 'ANSI_X3.4-1968'
emmmm…..果然!!!居然是ansi…
更改編碼:
import io,sys sys.stdout = io.TextIOWrapper(sys.stdout.buffer,encoding='utf-8') # 改變標准輸出的默認編碼
沒錯,問題就在這了。 怎么改呢。 這是類UNIX系統的標准輸出編碼問題。
首先, 把/etc/sysconfig/i18n里面的編碼改成xxxx.UTF-8
主要/重點:
然后,在/etc/profile中加入一行。export LC_ALL="UTF-8"
重啟
結果出師不利,在將爬取到的商品標題print出來時,拋出錯誤:
root@fb6e7c6fbe5c:/home/binss# python3 amazon_test.py | |
Traceback (most recent call last): | |
File "amazon_test.py", line 30, in | |
print(s) | |
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-7: ordinal not in range(128) |
Python2時代最怕就是這個UnicodeEncodeError,沒想到到了Python3,又見到它了。
查看第一個字符,發現為'\u8266',於是測試以下代碼:
>>> print('\u8266') |
果然報錯
Traceback (most recent call last): | |
File "", line 1, in | |
UnicodeEncodeError: 'ascii' codec can't encode character '\u8266' in position 0: ordinal not in range(128) |
嘗試了各種姿勢,結果還是沒能解決。
最后突發奇想,print不行,那我把其輸出到文件捏?
>>> s = '\u8266' | |
>>> with open('xxx.txt', mode='w') as pubilc_file: | |
... pubilc_file.write(s) |
依然報錯
Traceback (most recent call last): | |
File "", line 2, in | |
UnicodeEncodeError: 'ascii' codec can't encode character '\u8266' in position 0: ordinal not in range(128) |
那換成二進制輸出呢?
>>> s = '\u8266'.encode('utf-8') | |
>>> with open('xxx.txt', mode='wb') as pubilc_file: | |
... pubilc_file.write(s) |
竟然成功輸出了正確的字符——"艦"!這,難道是因為終端的stdout不支持utf-8輸出?
於是打印看看當前的stdout是啥
root@fb6e7c6fbe5c:/home/binss# python3 | |
Python 3.5.1 (default, Dec 18 2015, 00:00:00) | |
[GCC 4.8.4] on linux | |
Type "help", "copyright", "credits" or "license" for more information. | |
>>> import sys | |
>>> sys.stdout | |
<_io.TextIOWrapper name='' mode='w' encoding='ANSI_X3.4-1968'> | |
>>> |
這個ANSI_X3.4-1968的編碼是什么東西?怎么不是utf-8?以此為關鍵詞Google,終於搜到相關文章:
http://lab.knightstyle.info/私がpython3でunicodeencodeerrorなのはどう考えてもデフォルト文字/
大概意思就是如果要輸出utf-8,需要通過以下代碼將ANSI_X3.4-1968改為utf-8
import sys | |
import io | |
sys.stdout = io.TextIOWrapper(sys.stdout.buffer, encoding='utf-8') |
然后再次檢驗stdout是否為utf-8
>>> sys.stdout | |
<_io.TextIOWrapper name='' encoding='utf-8'> |
之后就可以愉快地print了
>>> print('\u8266') | |
艦 |