欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

告别乱码——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)