python打包中文报错,解决python3+Gooey使用pyinstaller打包时无法输出中文的问题

问题出处

代码如下:

# -*- coding: utf-8 -*-

from gooey import Gooey, GooeyParser

def run(keywords):

print(keywords)

@Gooey(

richtext_controls=True,  # 打开终端对颜色支持

language='chinese',

header_show_title=False,

program_name="test",  # 程序名称

encoding="utf-8",  # 设置编码格式,打包的时候遇到问题

progress_regex=r"^progress: (\d+)%$",  # 正则,用于模式化运行时进度信息

default_size=(905, 640),

)

def main():

description = "test"

parser = GooeyParser(description=description)

parser.add_argument('keywords', help="关键词")

args = parser.parse_args()

run(args.keywords)

main()

随手键入搜索引擎,发现其他地方也有人在询问或反馈类似问题,估计是个偏门问题,查找了一圈没有发现解决方案,所以献丑将解决方案记录于此,方便有需要的人查阅。

分析过程

python3.8环境,使用了Gooey的gui库(我也是第一次接触这个库),说打包后中文无法显示。

出于谨慎,我先将源码跑了一遍,发现很丝滑,没有丝毫问题。

随即使用pyinstaller将其进行打包,然而令人惊呆的事情出现了,用pyinstaller打包之后一运行输入中文就出错了(此处我是直接打包.py源码文件)。

感谢楼下@fanvalen 的热心回复补充,Gooey打包exe方法跟普通打包方式不一样,需要使用pyinstaller build.spec。详见@fanvalen 回复楼层。

实测使用build.spec方式打包依旧无法正常输出中文,并且该方式打包运行后输入中文不会出现报错信息,程序只会一直卡顿。本篇解决思路同样适用。

报错信息如下:

Exception in thread Thread-1:

Traceback (most recent call last):

File "threading.py", line 932, in _bootstrap_inner

File "threading.py", line 870, in run

File "gooey\gui\processor.py", line 70, in _forward_stdout

File "gooey\gui\processor.py", line 84, in _extract_progress

UnicodeDecodeError: 'utf-8' codec can't decode byte 0xc4 in position 0: invalid continuation byte

一看报错就发现是编码问题,所以想着要从编码入手。

解决思路

本着“大胆假设,小心求证”的精神,先将代码gooey的encoding="utf-8"参数改为gbk、gb2312、gb18030,无果,还直接报错。

随即换了个思路,是否是输出的编码有问题。

所以又将print语句的编码为utf-8、gbk再解码为utf-8、gbk,依旧无果。

本来想着就在代码里面改会简单快捷一点,但是无奈,看样子还是得回到报错代码上去了。

一看错误代码gooey/gui/processor.py的70行和84行,找到该库安装路径。

python安装路径下Libsite-packages/gooey/gui/processor.py

一眼就看到self.encoding这个参数很可疑。

通过追踪上下文的运行过程,发现有点儿意思,代码如下:

def _forward_stdout(self, process):

'''

Reads the stdout of `process` and forwards lines and progress

to any interested subscribers

'''

while True:

line = process.stdout.readline()  #同样的代码 打包前此处读取为utf-8编码 打包后却成为了gbk编码  所以一打包就无法输出中文 有兴趣的小伙伴可以print到控制台看结果

if not line:

break

_progress = self._extract_progress(line)

pub.send_message(events.PROGRESS_UPDATE, progress=_progress)

if _progress is None or self.hide_progress_msg is False:

pub.send_message(events.CONSOLE_UPDATE,

msg=line.decode("gbk"))  #decode默认参数self.encoding 改为gbk打包即可显示中文

pub.send_message(events.EXECUTION_COMPLETE)

def _extract_progress(self, text):

'''

Finds progress information in the text using the

user-supplied regex and calculation instructions

'''

# monad-ish dispatch to avoid the if/else soup

find = partial(re.search, string=text.strip().decode("gbk")) #decode默认参数self.encoding 改为gbk打包即可显示中文

regex = unit(self.progress_regex)

match = bind(regex, find)

result = bind(match, self._calculate_progress)

return result

同样的代码,打包前是utf-8编码,打包后又变成了gbk编码。

初步推测一下,可能是两个库都是老外编写的,某一个对中文的支持不太好。也可能是window下默认编码问题。(手动滑稽,哈哈哈哈)

因为打包后变成了gbk编码,所以解码自然就要解码为gbk。

两处参数一改,搞定,也就不想再继续深究了,本身对Gooey也不太感冒,虽然这是个很棒的作品。

请注意,打包完记得改回原来的参数,避免出现其他意外情况。

总结

这是一个治标不治本的方法,如果想要彻底解决,估计只有将pyinstaller的打包流程和Gooey的代码都深入研究一番,不然估计有点难。

window10环境下打包完之后自己实测跑了几波已经能够输出中文,未见其他异常,完美解决。其他系统请自测。

你可能感兴趣的:(python打包中文报错)