再次来到的中文标题,浅谈python编码管理

By admin in 4858.com on 2019年4月26日

 接上1篇,前两篇消除汉语的主题材料至关主假使在字符集上做的动作,就要普通话转成英文,可是有一种情形大家都不比做调换,即登6时服务器直接重临了华语内容:

以下内容转发自:

目前事务中要求用 Python 写一些剧本。尽管本子的交互只是命令行 +
日志输出,不过为了让界面友好些,我或然决定用汉语输出日志新闻。

  • 再次来到的中文标题,浅谈python编码管理。长时间以来,繁多人都知道,壹旦C++源码中一直动用了国文,那样的源码想要跨平台(I1八N)会卓殊不便。

4858.com 1

高效,笔者就遇上了丰裕:

随着:

那时先后报了之类错误,其实如故字符集难题:

 

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)  
  • Windows下:MSVC20拾改成主流
  • Linux下:GCC升级到4.6

4858.com 2

近年来作业中须求用 Python 写一些剧本。就算本子的相互只是命令行 +
日志输出,但是为了让分界面友好些,小编可能调节用普通话输出日志音信。 

为了消除难题,小编花时间去切磋了弹指间 Python
的字符编码管理。网络也有繁多小说讲 Python
的字符编码,不过本身看过2回,感到温馨能够讲得更明亮些。

C++中的普通话标题 才算有了3个比较优雅的、跨平台的Workaround。

为此:大家能够在接收数据的时候平昔对其进展丰富捕捉,如果这一个则换一种解码情势:

非常的慢,笔者就遇到了尤其: 

 

(本文商量编译器范围:GCC肆.六+, MSVC20拾sp一+
。本文属于QString体系,但暂不涉及QString)

def verification_ssh(host,username,password,port,root_pwd,cmd):
    s=paramiko.SSHClient()
    s.load_system_host_keys()
    s.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    s.connect(hostname = host,port=int(port),username=username, password=password)

    if username != 'root':
        ssh = s.invoke_shell()
        time.sleep(0.1)

        #先判断提示符,然后下一步在开始发送命令,这样大部分机器就都不会出现问题
        buff = ''
        while not buff.endswith('$ '):
            resp = ssh.recv(9999)
            try: #进行异常捕捉,如果解码有问题,则换一种解码方式
                buff += resp.decode('utf8')
            except Exception as e:
                buff += resp.decode('gb18030')
            print(resp)
            time.sleep(0.1)
        print('获取登录后的提示符:%s' %buff)


        ssh.send(' export LANG=en_US.UTF-8 \n') #解决错误的关键,编码问题
        ssh.send('export LANGUAGE=en \n')

        ssh.send('su - \n')

        buff = ""
        while not buff.endswith('Password: '): #true
            resp = ssh.recv(9999)
            print(resp)
            buff +=resp.decode('utf8')

        print('hhhhh')
        print(buff)

        ssh.send(root_pwd)
        ssh.send('\n')

        buff = ""
        # n = 0
        while not buff.endswith('# '):
            # n += 1
            resp = ssh.recv(9999)
            print(resp)
            buff +=resp.decode('utf8')
            # print(n)
            # if n >=3:
            #     break



        # print(buff)

        ssh.send('sh /tmp/check/101.sh') #放入要执行的命令
        ssh.send('\n')
        buff = ''
        # m = 0
        while not buff.endswith('# '):
            resp = ssh.recv(9999).decode()
            buff +=resp
            # m += 1
            # print(m)

        result  = buff
        # print(type(result))
        # print(result)
        s.close()

if __name__ == "__main__":
    verification_ssh('测试IP地址', '普通账号', '普通账号的密码', '52222', 'root密码', 'id')

UnicodeEncodeError: ‘ascii’ codec can’t encode characters in position 0-3: ordinal notin range(128) 

上边先复述一下 Python 字符串的根基,通晓此内容的能够跳过。

C++ 华语难点

要在C++中准确使用中文,必须求打听上边八个概念:

源码字符集(the source character set)

源码文件是使用何种编码保存的

执行字符集(the execution character set)

可执行程序内保存的是何种编码(程序执行时内存中字符串编码)

C++98的问题: 既未有规定源码字符集,也不曾规定施行字符集

以此… 如何知道?不妨看个例证

 

为了缓和难点,作者花时间去研讨了壹晃 Python
的字符编码处理。网络也有成都百货上千篇章讲 Python
的字符编码,可是本身看过贰回,感到自个儿能够讲得更了然些。 

对应 C/C++ 的 char 和 wchar_t, Python 也有三种字符串类型,str 与
unicode:

例子

那个供给高么?

  • 2个简易的C++程序,只是希望它能在简体汉语Windows、正体汉语Windows、英文版Windows、Linux、MAC
    OS…下的结果1致。

 

//main.cpp
int main()
{
    char mystr[] = "老老实实的学问,来不得半点马虎";
    return sizeof mystr;
}

能够试着反问本人多少个难点

  • 本条源码文件是何种编码保留的?(有规定答案么?)
  • mystr中是如何内容?(有明确答案么?)

对C++来讲,那四个都不显明。

  • 固定平台的话,仍是可以忍忍
  • 要跨平台的话,那种东西…

上一篇:ssh.invoke_shell()
切换root出现的新主题素材

上边先复述一下 Python 字符串的底蕴,熟习此内容的可以跳过。

# -*- coding: utf-8 -*-
# file: example1.py
import string

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

print isinstance(s, str)      # True
print isinstance(u, unicode)  # True

print s.__class__   # <type 'str'>
print u.__class__   # <type 'unicode'>

GCC

在GCC下,那多个都得以行使你自身喜好的编码(要是不点名,私下认可都是UTF8)

-finput-charset=charset
-fexec-charset=charset

除去前两个挑选外,还有一个:

-fwide-exec-charset=charset

wide? 不要紧先猜一下它是干嘛的

 注:转发请注脚出处

 

前方的申明:# -\– coding: utf-8 -*-* 表明,上面的 Python 代码由
utf-8 编码。

MSVC

MSVC未有像样前面包车型客车选项。

源码字符集如何解决?

有BOM么,有则按BOM解释,无则使用本地Locale字符集(随系统设置而变)

执行字符集如何解决?

使用本地Locale字符集(随系统设置而变)

挺霸道哈(当然,源码中可以动用#pragma setlocale("..."),但成效很有限,举个例子Windows未有utf8的locale,所以…)。

另外,和GCC对应的wide-exec-charset呢?

宽执行字符集如何解决?

不妨先考虑一下

对应 C/C++ 的 char 和 wchar_t, Python 也有二种字符串类型,str 与
unicode: 

为了保险输出不会在 linux 终端上展现乱码,必要安装好 linux
的情况变量:export LANG=en_US.UTF-8

怎么办?

那才三个编写翻译器,看起来就那样复杂了。而C++编写翻译器的数目远大于2.

要想跨平台,必须保险那八个字符集都以“显著”的,而能胜任该职务的字符集,仿佛美好的也只可以是…

# -*- coding: utf-8 -*-
# file: example1.py
import string

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

print isinstance(s, str)      # True
print isinstance(u, unicode)  # True

print s.__class__   # <type 'str'>
print u.__class__   # <type 'unicode'>

固然你和本身同1是采取 SecureCRT,请设置 Session
Options/Terminal/Appearance/Character Encoding 为 UTF-8,保障可以科学的解码 linux 终端的输出。

UTF-8方案

  • 壹经大家将源码保存成utf八,实行字符集也相中utf八,那么天下将太平了。使用非ASCII字符的源码文件也就能够在分化国度的用户间无障碍流通了 ;-).

源码保存成UTF-捌未有啥样困难,不过,实行字符集需倘若UTF-8。没那么简单

对GCC来讲,那个主题素材很简短(私下认可的编码选项丰硕了):

  • 若果源码文件保留成utf八就能够(带或不带BOM均可)
  • 早先时代的gcc不接收带BOM的utf八源码文件,现在,至少在GCC四.6中,这壹限制不再存在。

对MSVC来讲,这些主题素材相当复杂:

  • 对MSVC2003的话,只要源码保存成不带BOM的utf8就可以
  • 对MSVC二〇〇五、(没在SP一基础上装热补丁的)MSVC2010以来。完全不能够
  • 直到MSVC20十sp一,才算提供了一个化解方案。源码保存成带BOM的utf捌,utf1陆,…,然后加多

 

#pragma execution_character_set("utf-8")

要想跨GCC4.陆+和MSVC20十sp1+,大家要求取它们的交集:也正是

  • 源码保存成带BOM的utf8
  • 为MSVC添加#pragma

 

//main.cpp

#if _MSC_VER >= 1600
#pragma execution_character_set("utf-8")
#endif

int main()
{
    char mystr[] = "老老实实的学问,来不得半点马虎";
    return sizeof mystr;
}

前边的发明:# -\– coding: utf-8 -*-* 表明,上面的 Python 代码由 utf-8
编码。 

五个 Python 字符串类型间能够用 encode / decode 方法调换:

C++11

等到MSVC扶助C++1一的String
Literals之时,我们就没供给用至极不佳的pragma了,直接

    char mystr[] = u8"老老实实的学问,来不得半点马虎";

就可以(固然前些天在GCC下没难点,但要跨平台,猜测要等到Visual C++
12了)。

为了确定保障输出不会在 linux 终端上海展览中心示乱码,供给安装好 linux
的情状变量:export LANG=en_US.UTF-8 

# 从 str 转换成 unicode
print s.decode('utf-8')   # 关关雎鸠

# 从 unicode 转换成 str
print u.encode('utf-8')   # 关关雎鸠

有个难题?

C++玖第88中学不是有个wchar_t么,它不是用来代表unicode字符的么?

Unicode 4.0正规的5.二节是什么样说的:

 

The width of wchar_t is compiler-specific and can be as small as 8 bits. Consequently, programs that need to be portable across any C or C++ compilershould not use wchar_t for storing Unicode text. The wchar_t type is intended forstoring compiler-defined wide characters, which may be Unicode characters in some compilers.

在自己检查自纠看看GCC的抉择

-fwide-exec-charset=charset

就算GCC为其提供的暗中同意编码是UTF1陆或UTF3二(取决于wchar_t的小幅度),但该编码是能够自便安装的。

固然那几个东西不保险跨平台,也很倒霉玩, 可是,由于在windows下边wchar_t用来代表utf1六字符,而且直接对应系统API接口,所以在品种char16_t普遍以前,依然很要紧的。

一经你和自己同样是行使 SecureCRT,请设置 Session
Options/Terminal/Appearance/Character Encoding 为 UTF-8,保证能够正确的解码 linux 终端的输出。 

缘何从 unicode 转 str 是 encode,而扭曲叫 decode? 

C++1壹实施字符集

目前提到的u捌正是C++1一为“实施字符集”所做的竭力之1。

新鲜明规定了utf八、utf1六和utf32这3种实行字符集。

char*

u8"中文"

char16_t*

u"中文"

char32_t*

U"中文"

不过C++1一并未规定源码字符集

const char* mystr=u8"中文";

C++规范对编写翻译器说,作者随意这些文件的现实编码是怎么,但您不可能不给自己生成对应utf捌编码的字节流。

编写翻译器就如有点傻了啊?不知道源文件的编码,作者怎样更动

于是:

MSVC说:源码文件必须有BOM,否则笔者就认为你是当地locale的编码

GCC说:我以为你就是utf八编码,除非通过命令行通知本身任何编码

在C++11标准下,对源码编码 轻松的拍卖措施还是,使用带BOM的UTF八保存。

五个 Python 字符串类型间能够用 encode / decode 方法转变: 

因为 Python 感到 1陆 位的 unicode
才是字符的绝无仅有内码,而大家常用的字符集如
gb231二,gb18030/gbk,utf-八,以及 ascii
都以字符的二进制(字节)编码格局。把字符从 unicode
调换来2进制编码,当然是要 encode。

参考

  • from:

# 从 str 转换成 unicode
print s.decode('utf-8')   # 关关雎鸠

# 从 unicode 转换成 str
print u.encode('utf-8')   # 关关雎鸠

扭动,在 Python 中冒出的 str 都是用字符集编码的 ansi 字符串。Python
本人并不知道 str 的编码,要求由开拓者钦命正确的字符集 decode。

 为啥从 unicode 转 str 是 encode,而扭曲叫 decode?  

(补充一句,其实 Python 是能够知道 str
编码的。因为我们在代码后边注脚了 # -\– coding: utf-8
-*-*,那标记代码中的 str 都以用 utf-8 编码的,作者不知道 Python
为啥不那样做。)

因为 Python 认为 16 位的 unicode
才是字符的绝无仅有内码,而我们常用的字符集如
gb231二,gb18030/gbk,utf-捌,以及 ascii
都以字符的二进制(字节)编码格局。把字符从 unicode
调换到二进制编码,当然是要 encode。 

 

扭转,在 Python 中冒出的 str 都以用字符集编码的 ansi 字符串。Python
自个儿并不知道 str 的编码,需求由开采者钦命正确的字符集 decode。 

要是用错误的字符集来 encode/decode 会怎么样?

(补充一句,其实 Python 是足以驾驭 str
编码的。因为大家在代码前边申明了 #
-\
– coding: utf-8 -*-*,那表西夏码中的 str 都以用 utf-8编码的,作者不晓得 Python 为何不这么做。) 

# 用 ascii 编码含中文的 unicode 字符串
u.encode('ascii')  # 错误,因为中文无法用 ascii 字符集编码
                   # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

# 用 gbk 编码含中文的 unicode 字符串
u.encode('gbk')  # 正确,因为 '关关雎鸠' 可以用中文 gbk 字符集表示
                 # '\xb9\xd8\xb9\xd8\xf6\xc2\xf0\xaf'
                 # 直接 print 上面的 str 会显示乱码,修改环境变量为 zh_CN.GBK 可以看到结果是对的

# 用 ascii 解码 utf-8 字符串
s.decode('ascii')  # 错误,中文 utf-8 字符无法用 ascii 解码
                   # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

# 用 gbk 解码 utf-8 字符串
s.decode('gbk')  # 不出错,但是用 gbk 解码 utf-8 字符流的结果,显然只是乱码
                 # u'\u934f\u51b2\u53e7\u95c6\u5ea8\u7b2d'

若果用错误的字符集来 encode/decode 会怎么着?

那就遭受了作者在本文先河贴出的格外:UnicodeEncodeError: ‘ascii’ codec
can’t encode characters in position 0-三: ordinal not in range(128)

 

近期大家通晓了那是个字符串编码卓殊。接下来, 为何 Python
这么轻易并发字符串编/解码分外? 

# 用 ascii 编码含中文的 unicode 字符串
u.encode('ascii')  # 错误,因为中文无法用 ascii 字符集编码
                   # UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)

# 用 gbk 编码含中文的 unicode 字符串
u.encode('gbk')  # 正确,因为 '关关雎鸠' 可以用中文 gbk 字符集表示
                 # '\xb9\xd8\xb9\xd8\xf6\xc2\xf0\xaf'
                 # 直接 print 上面的 str 会显示乱码,修改环境变量为 zh_CN.GBK 可以看到结果是对的

# 用 ascii 解码 utf-8 字符串
s.decode('ascii')  # 错误,中文 utf-8 字符无法用 ascii 解码
                   # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

# 用 gbk 解码 utf-8 字符串
s.decode('gbk')  # 不出错,但是用 gbk 解码 utf-8 字符流的结果,显然只是乱码
                 # u'\u934f\u51b2\u53e7\u95c6\u5ea8\u7b2d'

那要提四管理 Python 编码时便于碰着的四个圈套。第三个是关于字符串连接的:

 

# -*- coding: utf-8 -*-
# file: example2.py

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

s + u  # 失败,UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

4858.com ,那就碰到了本人在本文开端贴出的相当:UnicodeEncodeError: ‘ascii’ codec
can’t encode characters in position 0-3: ordinal not in range(12八)

简单的字符串连接也会合世解码错误?

 以后大家掌握了那是个字符串编码非凡。接下来, 为何 Python
这么轻易并发字符串编/解码非凡? 

 

 那要提到处理 Python
编码时便于际遇的四个圈套。第一个是关于字符串连接的:

陷阱一:在拓展同时含有 str 与 unicode 的演算时,Python 一律都把 str
调换来 unicode 再运算,当然,运算结果也都是 unicode。

 

是因为 Python 事先并不知道 str 的编码,它只可以选用 sys.getdefaultencoding()
编码去 decode。在小编的回想里,sys.getdefaultencoding() 的值总是 ‘ascii’
——显著,假设须求更动的 str 有普通话,一定会现出谬误。

# -*- coding: utf-8 -*-
# file: example2.py

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

s + u  # 失败,UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

除了这些之外字符串连接,% 运算的结果也是均等的:

简易的字符串连接也会冒出解码错误? 

# 正确,所有的字符串都是 str, 不需要 decode
"中文:%s" % s   # 中文:关关雎鸠

# 失败,相当于运行:"中文:%s".decode('ascii') % u
"中文:%s" % u  # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

# 正确,所有字符串都是 unicode, 不需要 decode
u"中文:%s" % u   # 中文:关关雎鸠

# 失败,相当于运行:u"中文:%s" % s.decode('ascii')
u"中文:%s" % s  # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

陷阱1:在开始展览同时富含 str 与 unicode 的演算时,Python 一律都把 str
转变到 unicode 再运算,当然,运算结果也都以 unicode。 

自个儿不知情为啥 sys.getdefaultencoding() 与情状变量 $LANG 全毫不相关系。倘使Python 用 $LANG 设置 sys.getdefaultencoding() 的值,那么至少开辟者碰到UnicodeDecodeError 的可能率会降低 3/陆。

鉴于 Python 事先并不知道 str 的编码,它不得不采取 sys.getdefaultencoding()
编码去 decode。在自身的影像里,sys.getdefaultencoding() 的值总是 ‘ascii’
——显明,假如须要改造的 str 有普通话,一定会冒出谬误。 

其余,就如前边说的,小编也出乎意料为何 Python 在那里不参考 # -\– coding:
utf-8 -*-* ,因为 Python
在运行前总是会检讨你的代码,那保障了代码里定义的 str 一定是 utf-捌 。

除了字符串连接,% 运算的结果也是一样的: 

 

# 正确,所有的字符串都是 str, 不需要 decode
"中文:%s" % s   # 中文:关关雎鸠

# 失败,相当于运行:"中文:%s".decode('ascii') % u
"中文:%s" % u  # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

# 正确,所有字符串都是 unicode, 不需要 decode
u"中文:%s" % u   # 中文:关关雎鸠

# 失败,相当于运行:u"中文:%s" % s.decode('ascii')
u"中文:%s" % s  # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

对此那些难题,小编的绝无仅有提出是在代码里的国语字符串前写上 u。其它,在
Python 三 曾经撤废了 str,让具有的字符串都以 unicode
——那恐怕是个准确的主宰。

本人不晓得为啥 sys.getdefaultencoding() 与景况变量 $LANG 全无关系。假如Python 用 $LANG 设置 sys.getdefaultencoding() 的值,那么至少开拓者际遇UnicodeDecodeError 的可能率会降低 50%。 

实质上,sys.getdefaultencoding()
的值是足以用“后门”格局修改的,笔者不是特意推荐那几个化解方案,然则依然贴一下,因为前面有用:

此外,就好像前边说的,笔者也出乎意料为何 Python 在此地不参考 # -\– coding: utf-8 -*-* ,因为
Python 在运行前线总指挥部是会检查你的代码,那有限支持了代码里定义的 str 一定是 utf-八。 

# -*- coding: utf-8 -*-
# file: example3.py
import sys

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 使得 sys.getdefaultencoding() 的值为 'utf-8'
reload(sys)                      # reload 才能调用 setdefaultencoding 方法
sys.setdefaultencoding('utf-8')  # 设置 'utf-8'

# 没问题
s + u  # u'\u5173\u5173\u96ce\u9e20\u5173\u5173\u96ce\u9e20'

# 同样没问题
"中文:%s" % u   # u'\u4e2d\u6587\uff1a\u5173\u5173\u96ce\u9e20'

# 还是没问题
u"中文:%s" % s  # u'\u4e2d\u6587\uff1a\u5173\u5173\u96ce\u9e20'

对此这几个标题,小编的唯第二建工公司议是在代码里的中文字符串前写上 u。其余,在
Python 3 早已撤除了 str,让抱有的字符串都以 unicode
——那或者是个科学的支配。 

能够看来,难题魔术般的消除了。可是注意! sys.setdefaultencoding()
的法力是全局的,倘使你的代码由多少个不等编码的 Python
文件组成,用这种情势只是按下了葫芦浮起了瓢,让难题变得复杂。

实质上,sys.getdefaultencoding()
的值是能够用“后门”格局修改的,笔者不是特地推荐这么些化解方案,不过仍然贴一下,因为背后有用: 

 

# -*- coding: utf-8 -*-
# file: example3.py
import sys

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 使得 sys.getdefaultencoding() 的值为 'utf-8'
reload(sys)                      # reload 才能调用 setdefaultencoding 方法
sys.setdefaultencoding('utf-8')  # 设置 'utf-8'

# 没问题
s + u  # u'\u5173\u5173\u96ce\u9e20\u5173\u5173\u96ce\u9e20'

# 同样没问题
"中文:%s" % u   # u'\u4e2d\u6587\uff1a\u5173\u5173\u96ce\u9e20'

# 还是没问题
u"中文:%s" % s  # u'\u4e2d\u6587\uff1a\u5173\u5173\u96ce\u9e20'

另一个骗局是关于标准输出的。

能够看出,难题魔术般的消除了。但是注意! sys.setdefaultencoding()
的效应是大局的,假诺你的代码由多少个差异编码的 Python
文件组成,用那种艺术只是按下了葫芦浮起了瓢,让难点变得复杂。 

恰恰怎么来着?小编平素说要设置科学的 linux $LANG
遇到变量。那么,设置错误的 $LANG,举个例子 zh_CN.GBK
会怎么着?(防止终端的震慑,请把 SecureCRT 也设置成同样的字符集。)

另多个陷阱是有关专门的事业输出的。 

可想而知会是乱码,可是还是不是持有出口都是乱码。

恰恰怎么来着?我向来说要安装科学的 linux $LANG
碰到变量。那么,设置错误的 $LANG,例如 zh_CN.GBK
会怎么着?(幸免终端的震慑,请把 SecureCRT 也设置成一样的字符集。) 

# -*- coding: utf-8 -*-
# file: example4.py
import string

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 输出 str 字符串, 显示是乱码
print s   # 鍏冲叧闆庨笭

# 输出 unicode 字符串,显示正确
print u  # 关关雎鸠

领悟会是乱码,不过不是具有出口都以乱码。

为何是 unicode 而不是 str 的字符展现是不错的? 首先大家须要理解print。与具备语言一样,这些 Python 命令实际上是把字符打字与印刷到正规输出流 ——
sys.stdout。而 Python 在那边变了个魔术,它会遵从 sys.stdout.encoding
来给 unicode 编码,而把 str 直接出口,扔给操作系统去解决。

 

这也是干什么要设置 linux $LANG 情形变量与 SecureCRT
1致,不然那些字符会被 SecureCRT 再转变3回,才会付出桌面包车型地铁 Windows
系统用编码 CP93陆 只怕说 GBK 来展现。

# -*- coding: utf-8 -*-
# file: example4.py
import string

# 这个是 str 的字符串
s = '关关雎鸠'

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 输出 str 字符串, 显示是乱码
print s   # 鍏冲叧闆庨笭

# 输出 unicode 字符串,显示正确
print u  # 关关雎鸠

一般说来状态,sys.stdout.encoding 的值与 linux $LANG 景况变量保持一致:

 

# -*- coding: utf-8 -*-
# file: example5.py
import sys

# 检查标准输出流的编码
print sys.stdout.encoding  # 设置 $LANG = zh_CN.GBK,  输出 GBK
                           # 设置 $LANG = en_US.UTF-8,输出 UTF-8

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 输出 unicode 字符串,显示正确
print u  # 关关雎鸠

缘何是 unicode 而不是 str 的字符显示是不利的? 首先大家须要精晓print。与具备语言一样,那些 Python 命令实际上是把字符打字与印刷到标准输出流 ——
sys.stdout。而 Python 在此地变了个魔术,它会根据 sys.stdout.encoding
来给 unicode 编码,而把 str 直接出口,扔给操作系统去消除。 

但是,这里有 陷阱二:1旦您的 Python 代码是用管道 /
子进度方式运转,sys.stdout.encoding 就会失效,让您再一次境遇UnicodeEncodeError。

那也是为何要设置 linux $LANG 景况变量与 SecureCRT
1致,否则这个字符会被 SecureCRT 再转移贰回,才会付给桌面的 Windows
系统用编码 CP93六 或然说 GBK 来显示。 

譬如,用管道情势运营方面包车型客车 example四.py 代码:

日常状态,sys.stdout.encoding 的值与 linux $LANG 情状变量保持一致:

python -u example5.py | more

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

 

能够观察,第一:sys.stdout.encoding 的值形成了
None;第二:Python 在 print 时会尝试用 ascii 去编码 unicode.

# -*- coding: utf-8 -*-
# file: example5.py
import sys

# 检查标准输出流的编码
print sys.stdout.encoding  # 设置 $LANG = zh_CN.GBK,  输出 GBK
                           # 设置 $LANG = en_US.UTF-8,输出 UTF-8

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 输出 unicode 字符串,显示正确
print u  # 关关雎鸠

鉴于 ascii 字符集不可能用来表示中文字符,这里当然会编码失利。

 

怎么化解那几个主题材料? 不精通别人是怎么消除的,总来说之作者用了三个其貌不扬的方法:

只是,那里有 陷阱2:1旦您的 Python
代码是用管道 / 子进度情势运维,sys.stdout.encoding
就会失灵,让您再度碰着 UnicodeEncodeError。 

# -*- coding: utf-8 -*-
# file: example6.py
import os
import sys
import codecs

# 无论如何,请用 linux 系统的当前字符集输出:
if sys.stdout.encoding is None:
    enc = os.environ['LANG'].split('.')[1]
    sys.stdout = codecs.getwriter(enc)(sys.stdout)  # 替换 sys.stdout

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 输出 unicode 字符串,显示正确
print u  # 关关雎鸠

譬如,用管道形式运转方面包车型地铁 example4.py 代码:

以此点子照旧有个副效用:直接出口闽南语 str 会失利,因为 codecs 模块的
writer 与 sys.stdout 的一坐一起相反,它会把具备的 str 用
sys.getdefaultencoding() 的字符集调换到 unicode 输出。

python -u example5.py | more

UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-3: ordinal not in range(128)
None
# 这个是 str 的字符串
s = '关关雎鸠'

# 输出 str 字符串, 异常
print s   # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

 

让人惊叹,sys.getdefaultencoding() 的值是 ‘ascii’, 编码战败。

能够看看,第二:sys.stdout.encoding 的值形成了 None;第3:Python 在
print 时会尝试用 ascii 去编码 unicode. 

 

鉴于 ascii 字符集不能够用来表示普通话字符,那里当然会编码败北。 

消除办法就如 example叁.py 里说的,你要么给 str 加上 u 注脚成
unicode,要么通过“后门”去修改 sys.getdefaultencoding():

怎么化解那几个难题? 不清楚外人是怎么消除的,同理可得笔者用了三个猥琐的点子: 

# 使得 sys.getdefaultencoding() 的值为 'utf-8'
reload(sys)                      # reload 才能调用 setdefaultencoding 方法
sys.setdefaultencoding('utf-8')  # 设置 'utf-8'

# 这个是 str 的字符串
s = '关关雎鸠'

# 输出 str 字符串, OK
print s   # 关关雎鸠
# -*- coding: utf-8 -*-
# file: example6.py
import os
import sys
import codecs

# 无论如何,请用 linux 系统的当前字符集输出:
if sys.stdout.encoding is None:
    enc = os.environ['LANG'].split('.')[1]
    sys.stdout = codecs.getwriter(enc)(sys.stdout)  # 替换 sys.stdout

# 这个是 unicode 的字符串
u = u'关关雎鸠'

# 输出 unicode 字符串,显示正确
print u  # 关关雎鸠

简单来讲,在 Python 二下张开汉语输入输出是个风险4伏的事,尤其是在你的代码里掺杂使用 str 与
unicode 时。

 

 

其一法子依然有个副作用:直接出口汉语 str 会退步,因为 codecs 模块的
writer 与 sys.stdout 的行事相反,它会把具备的 str 用
sys.getdefaultencoding() 的字符集转换来 unicode 输出。 

些微模块,举个例子 json,会直接重回 unicode 类型的字符串,让您的 %
运算须求展开字符解码而小败。而有点会直接重返 str,
你须要精晓它们的真人真事编码,尤其是在 print 的时候。

# 这个是 str 的字符串
s = '关关雎鸠'

# 输出 str 字符串, 异常
print s   # UnicodeDecodeError: 'ascii' codec can't decode byte 0xe5 in position 0: ordinal not in range(128)

为了防止有个别陷阱,上文中说过,最佳的点子就是在 Python 代码里永恒使用 u
定义粤语字符串。别的,借使您的代码供给用管道 /
子进度格局运营,则须求用到 example陆.py 里的技巧。

显明,sys.getdefaultencoding() 的值是 ‘ascii’, 编码退步。 

(完)

化解办法就像是 example3.py 里说的,你要么给 str 加上 u 声明成
unicode,要么通过“后门”去修改 sys.getdefaultencoding(): 

正文转自  

# 使得 sys.getdefaultencoding() 的值为 'utf-8'
reload(sys)                      # reload 才能调用 setdefaultencoding 方法
sys.setdefaultencoding('utf-8')  # 设置 'utf-8'

# 这个是 str 的字符串
s = '关关雎鸠'

# 输出 str 字符串, OK
print s   # 关关雎鸠

一言以蔽之,在 Python 二下展开汉语输入输出是个风险4伏的事,尤其是在你的代码里夹杂使用 str 与
unicode 时。 

某个模块,举例 json,会一向回到 unicode 类型的字符串,让你的 %
运算供给张开字符解码而未果。而有点会一贯回到 str,
你须要精通它们的真人真事编码,特别是在 print 的时候。 

为了幸免某些骗局,上文中说过,最棒的章程正是在 Python 代码里恒久使用 u
定义中文字符串。此外,假设你的代码须要用管道 /
子进度方式运转,则供给用到 example6.py 里的才能。

 

(完)

发表评论

电子邮件地址不会被公开。 必填项已用*标注

网站地图xml地图
Copyright @ 2010-2019 美高梅手机版4858 版权所有