告别乱码——7行代码判断当前python运行编码,是控制台还是IDE(如PyCharm)

由于众所周知的原因,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)
发布了25 篇原创文章 · 获赞 22 · 访问量 9331

猜你喜欢

转载自blog.csdn.net/qq_27884799/article/details/93662701