python学习笔记 --- setdefaultencoding() : reload(sys)后没法正常执行命令的缘由

写在前面

一个很难找到问题所在的问题,后来是经过网上的博文才知道了是怎么样的缘由,reload(sys)不能随便用,由于一旦重置了,不少环境变量就不同了。python

正文

搞搞编码

首先是问题的来源:ubuntu

我在写python脚本遇到了下面这个问题函数

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

至关不能理解,这其实就涉及了python里面至关复杂的编码的问题。在python中运行的字符串都是unicode编码的,为何须要这么一个中间的编码,实际上是颇有用的,保证了编码与编码之间的互通性。编码

首先,你们确定知道encode和decode,用法以下code

str = 'dafd'
unicode_str = str.decode('gb2312') #这表示将gb2312编码的str转化成unicode
unicode_str.encode('utf-8') #这表示将unicode编码的unicode_str转化成utf-8编码

所以,转码的时候必定要先搞明白,字符串str是什么编码,而后decode成unicode,而后再encode成其余编码utf-8

另外,
代码中字符串的默认编码与代码文件自己的编码一致。记住!~ci

如:s='中文'

若是是在utf8的文件中,该字符串就是utf8编码,若是是在gb2312的文件中,
则其编码为gb2312。这种状况下,要进行编码转换,
都须要先用decode方法将其转换成unicode编码,
再使用encode方法将其转换成其余编码。一般,在没有指定特定的编码方式时,都是使用的系统默认编码建立的代码文件。 

若是字符串是这样定义:s=u'中文'

则该字符串的编码就被指定为unicode了,即python的内部编码,
而与代码文件自己的编码无关。所以,对于这种状况作编码转换,只须要直接使用encode方法将其转换成指定编码便可。

若是一个str已是unicode了,这时候再去decode就会出错,很好理解。unicode

得到系统的默认编码字符串

#!/usr/bin/env python
#coding=utf-8
import sys
print sys.getdefaultencoding()  

该段程序在英文WindowsXP上输出为:ascii 
但其实在ubuntu里也是这样的问题,这其实就是我写这篇文章的初衷,由于我被这个问题困扰了好久!

s = '你好'
print s

输出控制台的编码是ascii时,若是你print的是unicode就会出现这个错误:terminal

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-1: ordinal not in range(128)

只要改为 print s.encode('utf-8')就ok了。

为何要reload(sys)

刚刚这么讲好像就解决了?其实不是的,我有个函数tf.train.BytesList,这个函数的参数是一个str,可是这个str的编码由于系统默认编码的缘由出错了,就是上面的错。这时候的解决办法通常是reload(sys)。

可是,你会看到卡住了?实际上是输出看不到了,网上有这样的解答。

IDLE做为一个GUI Shell环境,在启动初始化过程当中,
会设置特定的标准输入、标准输出和标准错误输出,使得输入和输出都在IDLE的GUI Shell中。
而若是手动执行了reload(sys)之后,sys模块的这三个变量将会被重置,
致使输出没法显示在IDLE。因此解决方案很简单,只须要在reload以前把这三个变量都复制一份,reload以后再恢复回来就好了

上面的IDLE其实不仅是IDLE,像我就是在jupyter的状况下出错的,terminal下也是同样。因此要记得补上如下代码:

stdi,stdo,stde=sys.stdin,sys.stdout,sys.stderr
reload(sys)
sys.stdin,sys.stdout,sys.stderr=stdi,stdo,stde

ok!就写到这,祝你们coding愉快~

相关文章
相关标签/搜索