通透到底解决ssh,浅谈python编码管理

 接上壹篇,前两篇解决中文的标题至关心珍爱要是在字符集上做的小动作,将在汉语转成英文,可是有一种意况大家都来比不上做转变,即登入时服务器直接回到了国文内容:

以下内容转发自:

目前事情中须要用 Python 写一些剧本。就算本子的竞相只是命令行 +
日志输出,可是为了让分界面友好些,作者依然调整用中文输出日志消息。

  • 长时间以来,诸多人都晓得,一旦C++源码中向来利用了华语,那样的源码想要跨平台(I18N)会尤其困难。

澳门葡京备用网址 1

神速,小编就蒙受了这多少个:

随着:

此刻先后报了之类错误,其实照旧字符集难题:

 

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

澳门葡京备用网址 2

方今事情中必要用 Python 写一些剧本。纵然本子的互相只是命令行 +
日志输出,可是为了让分界面友好些,作者依旧调控用汉语输出日志新闻。 

为了消除难题,我花时间去探讨了须臾间 Python
的字符编码处理。英特网也有数不胜数小说讲 Python
的字符编码,可是本身看过3次,感到温馨能够讲得更了然些。

C++中的粤语难题 才算有了1个相比较优雅的、跨平台的Workaround。

为此:我们得以在接收数据的时候一贯对其实行万分捕捉,假若那么些则换一种解码方式:

高效,我就凌驾了要命: 

 

(本文商量编写翻译器范围:GCC4.陆+, 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:

例子

本条需要高么?

  • 三个简短的C++程序,只是希望它能在简体普通话Windows、正体汉语Windows、英文版Windows、Linux、MAC
    OS…下的结果壹律。

 

//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下,那五个都足以采取你自身喜好的编码(即使不点名,暗中认可都以UTF八)

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

除了前四个挑选外,还有三个:

-fwide-exec-charset=charset

wide? 无妨先猜一下它是干嘛的

 注:转发请注解出处

 

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

通透到底解决ssh,浅谈python编码管理。MSVC

MSVC未有像样前边的选项。

源码字符集如何解决?

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

执行字符集如何解决?

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

挺霸道哈(当然,源码中得以应用#pragma setlocale("..."),但成效很单薄,比方Windows未有utf八的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-八,保险能够准确的解码 linux 终端的出口。

UTF-8方案

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

源码保存成UTF-八未有啥困难,但是,实行字符集需如若UTF-8。没那么轻易

对GCC来讲,那些难点相当粗略(暗许的编码选项丰硕了):

  • 一旦源码文件保留成utf八就可以(带或不带BOM均可)
  • 早期的gcc不接收带BOM的utf八源码文件,未来,至少在GCC4.陆中,这一范围不再存在。

对MSVC来讲,这些主题素材丰盛复杂:

  • 对MSVC200三的话,只要源码保存成不带BOM的utf八就可以
  • 对MSVC200五、(没在SP一基础上装热补丁的)MSVC二〇一〇以来。完全不能
  • 直至MSVC20十sp1,才算提供了3个化解方案。源码保存成带BOM的utf八,utf16,…,然后加多

 

#pragma execution_character_set("utf-8")

要想跨GCC肆.陆+和MSVC20十sp一+,我们供给取它们的混杂:也便是

  • 源码保存成带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之时,大家就没供给用1二分倒霉的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用来表示utf16字符,而且一向对应系统API接口,所以在类型char1陆_t广泛从前,依旧很要紧的。

假若你和自家一样是利用 SecureCRT,请设置 Session
Options/Terminal/Appearance/Character Encoding 为 UTF-八,保障能够科学的解码 linux 终端的输出。 

干什么从 unicode 转 str 是 encode,而扭曲叫 decode? 

C++1壹推行字符集

前边提到的u八正是C++1壹为“推行字符集”所做的努力之一。

新明显规定了utf八、utf1六和utf3②那三种实行字符集。

char*

u8"中文"

char16_t*

u"中文"

char32_t*

U"中文"

只是C++11并未分明源码字符集

const char* mystr=u8"中文";

C++标准对编写翻译器说,作者随意那么些文件的有血有肉编码是什么,但你无法不给自个儿生成对应utf八编码的字节流。

编写翻译器就如有点傻了呢?不知道源文件的编码,小编如何改变

于是:

MSVC说:源码文件必须有BOM,不然小编就认为你是地面locale的编码

GCC说:笔者以为你就是utf捌编码,除非通过命令行公告作者任何编码

在C++1一正经下,对源码编码 轻易的管理格局依然,使用带BOM的UTF八保存。

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

因为 Python 感到 16 位的 unicode
才是字符的绝无仅有内码,而大家常用的字符集如
gb231二,gb18030/gbk,utf-八,以及 ascii
都以字符的二进制(字节)编码情势。把字符从 unicode
调换到二进制编码,当然是要 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-八 编码的,作者不掌握 Python
为啥不这么做。)

因为 Python 认为 1陆 位的 unicode
才是字符的唯1内码,而大家常用的字符集如
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'

1经用错误的字符集来 encode/decode 会如何?

那就碰见了本身在本文开始贴出的那一个:UnicodeEncodeError: ‘ascii’ codec
can’t encode characters in position 0-叁: ordinal not in range(12八)

 

今昔我们知晓了那是个字符串编码相当。接下来, 为啥 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)

那就碰着了自个儿在本文起初贴出的那三个: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 的概率会降低 百分之五十。

是因为 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 的可能率会骤降 1贰分之伍。 

实际,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 三 业已撤除了 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'

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

能够观望,难题魔术般的化解了。不过注意! 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
壹致,不然这个字符会被 SecureCRT 再调换一次,才会付给桌面的 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 情况变量保持1致:

 

# -*- 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 直接出口,扔给操作系统去化解。 

但是,这里有 陷阱二:一旦你的 Python 代码是用管道 /
子进程情势运行,sys.stdout.encoding 就会失效,让你再度遭遇UnicodeEncodeError。

那也是干什么要设置 linux $LANG 意况变量与 SecureCRT
壹致,否则这个字符会被 SecureCRT 再调换1遍,才会付出桌面包车型大巴 Windows
系统用编码 CP93陆 可能说 GBK 来展现。 

诸如,用管道形式运转方面包车型客车 example肆.py 代码:

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

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 字符集不能够用来代表粤语字符,那里当然会编码失利。

 

怎么化解那些主题素材? 不领悟旁人是怎么消除的,由此可知作者用了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  # 关关雎鸠

比方,用管道方式运转方面包车型客车 example四.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’, 编码战败。

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

 

出于 ascii 字符集不可能用来代表粤语字符,那里当然会编码失利。 

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

怎么消除这一个标题? 不亮堂外人是怎么解决的,综上说述作者用了3个其貌不扬的点子: 

# 使得 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 2下实行粤语输入输出是个风险4伏的事,尤其是在你的代码里夹杂使用 str 与
unicode 时。 

稍加模块,比如 json,会一贯回到 unicode 类型的字符串,让你的 %
运算必要举行字符解码而败诉。而某些会一贯回到 str,
你要求精通它们的忠实编码,特别是在 print 的时候。 

为了防止有些圈套,上文中说过,最棒的不二法门正是在 Python 代码里长久使用 u
定义粤语字符串。其余,即使您的代码必要用管道 /
子进程方式运营,则须求用到 example陆.py 里的才能。

 

(完)

相关文章

发表评论

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

*
*
Website