告别乱码——7行代码判断当前python运行编码,是控制台还是IDE(如PyCharm)
程序员文章站
2022-06-01 12:06:01
...
由于众所周知的原因,python中的PyCharm输出时使用utf-8编码,而控制台窗体里则遵循系统编码。在windows简中版本下,系统使用gbk编码,而调试用的PyCharm使用UTF-8,这就带来了一系列困扰人的问题。这些问题在python2尤甚,但python3里,读写文件、执行cmd命令等仍然会发生乱码。(由于Linux默认UTF-8编码,在纯Linux下并不发生这类问题)
比如,调试好好的编码
# coding: utf-8
print "你好"
在PyCharm里输出正常。但在cmd里执行,或者编译为exe以后,就变成了
浣犲ソ
如果我们为了打包后不乱码,这样处理
# coding: utf-8
print "你好".decode('utf-8').encode('gbk')
那么在cmd里执行正常,但我们要在PyCharm里调试时,就又乱码了
���
一个方法是重写print和input函数
# coding: utf-8
USECONSOLE = True
def print(statement):
if USECONSOLE:
print(str(statement).decode('utf-8').encode('gbk'))
else:
print(statement)
def input(hint):
try:
in = raw_input
except:
in = input
if USECONSOLE:
return in(str(hint).decode('utf-8').encode('gbk')).decode('gbk').encode('utf-8')
else:
return in(hint)
然后在打包和控制台运行时,把USECONSOLE设为True;在IDE下工作的时候,就要设为False。你所有的文件都导入这里的input和print方法即可
但是,有没有办法不用频繁切换True和False,只通过代码来判断呢?
网上多无此类资料,经过多次尝试,发现解决方案竟如此简单
# coding: utf-8
from ctypes import *
import six
hwnd = windll.user32.GetForegroundWindow()
out = windll.kernel32.GetStdHandle(-0xb) # stdin: 0xa, stdout: 0xb, stderr: 0xc
rtn = windll.kernel32.SetConsoleTextAttribute(out, 0x7)
six.print_(u"你正在使用控制台" if rtn else u"你正在使用IDE")
six.moves.input("")
原理是拿到了当前活动窗体的标准输出句柄,并尝试为其设置颜色。如能设置,则为控制台,此时SetConsoleTextAttribute调用成功,返回非0值;反之,在IDE下调用SetConsoleTextAttribute设置颜色会报错,返回的是0值。根据此值可以判断运行的环境。
上面的模块代码最终改写为
# coding: utf-8
from ctypes import *
hwnd = windll.user32.GetForegroundWindow()
out = windll.kernel32.GetStdHandle(-0xb) # stdin: 0xa, stdout: 0xb, stderr: 0xc
USECONSOLE = bool(windll.kernel32.SetConsoleTextAttribute(out, 0x7))
def print(statement):
if USECONSOLE:
print(str(statement).decode('utf-8').encode('gbk'))
else:
print(statement)
def input(hint):
try:
in = raw_input
except:
in = input
if USECONSOLE:
return in(str(hint).decode('utf-8').encode('gbk')).decode('gbk').encode('utf-8')
else:
return in(hint)