起因

在论坛悬赏区看到一个求助,python3.8环境,使用了Gooey的gui库,说打包后中文无法显示。

代码如下:

# -*- 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()

分析过程

拿起代码一跑,没有发现丝毫问题。

随即将其进行打包,然而令人惊呆的事情出现了,用pyinstaller打包之后一运行就出错了(小声bb一下,感觉这些老外的作品对有时候对中文支持不太好,反正没少遇到编码问题,当然,也可能是我使用的姿势有问题)。

错误代码如下:

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,依旧无果。

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

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

python安装路径下Libsite-packagesgooeyguiprocessor.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(self.encoding))  #默认参数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(self.encoding)) #默认参数self.encoding 改为gbk打包即可显示中文
        regex = unit(self.progress_regex)
        match = bind(regex, find)
        result = bind(match, self._calculate_progress)
        return result

同样的代码,打包前是utf-8编码,打包后又变成了gbk编码。所以每次就报错解码为utf-8失败。

因为打包后变成了gbk编码,所以就解码自然就要解码为gbk。两个一填,搞定,也就不想再继续深究了,本身对Gooey也不太感冒,虽然这是个很棒的作品。(请注意,打包完记得改回原来的参数,避免出现其他意外情况。

寻思着要么是打包出现了问题,要么gooey本身对编码的支持有点问题(但是不打包也没问题,虽然不打包也不能选gbk编码)。

解决后,我在搜索引擎试图查看有无其他思路,发现貌似网上没有找到解决这个思路,可能使用的人又或者使用了还打包的人比较少。

也发现有人在问同样的问题,所以随手记在这里,方便有需要的人参考。

一句话总结

大胆假设,小心求证。反正也不影响自己耍帅。

ps:如果有人看到,并且有更好的解决方案,记得给我安利一下,看看别人的思路。


本文由 大古 创作,采用 知识共享署名 3.0,可自由转载、引用,但需署名作者且注明文章出处。

还不快抢沙发

添加新评论