原程序运行良好,Pyinstaller

发布时间:2019-09-28 08:38:47编辑:auto阅读(1995)

    前言

    昨天决定分享一下最近写的exhentai爬虫程序,参考了这篇文章,看了下里面几个常见打包软件的简介表格(可惜没nuitka)
    因为是给小白用户使用,做成单个文件形式,只能在Pyinstaller和py2exe之间选择
    去各自官网看了下,发现py2exe很久没更新了,对python3新版本的支持也不是太好,就决定用Pyinstaller来封装/打包
    这里略过Pyinstaller的安装和使用,重点说明症状,分析过程,解决办法和教训

    症状

    1. 打包成功

    2. 运行程序时出现如下报错

    C:\Users\xoxo\PycharmProjects\Hentai_Spider>main
    Traceback (most recent call last):
      File "main.py", line 6, in <module>
        from config import args
      File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
      File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 1129, in _exec
      File "C:\Python34\lib\site-packages\PyInstaller\loader\pyimod03_importers.py",
     line 631, in exec_module
        exec(bytecode, module.__dict__)
      File "config.py", line 11, in <module>
        parser.add_argument('-sd', '--savedir', default=config['ARGS']['SAVEDIR'])
      File "configparser.py", line 936, in __getitem__
    KeyError: 'ARGS'
    [7836] Failed to execute script main
    
    C:\Users\xoxo\PycharmProjects\Hentai_Spider>

    分析过程

    0 . StackOverflow搜了下发现没啥经验可供参考……
    1 . main.py程序是完全可以跑通的,从未出现过这个报错,所以确定问题出在封装过程中
    2 . 报错信息上看,是(封装后的程序)执行config.py时出了问题
    3 . 通过控制变量排除法(过程比较繁琐,不一一列举),确定是在读取config.ini时出的错,把赋值config_path这里改成确定的路径即可正常运行

    代码如下:

    config = configparser.ConfigParser()
    config_path = os.path.join(os.path.dirname(__file__), CONFIG_FILE)
    config.read(config_path)

    顺便解释一下,我的设计意图是让config.py去读取其所在目录下的配置文件,main.py和config.py在同一目录

    4 . 由于CONFIG_FILE是常量(文件名),那最终就怀疑到os.path.dirname(__file__)部分
    5 . 在赋值config_path =这句后加上print(os.path.dirname(__file__),看看封装后这里的file会到哪个目录,发现变成了C:\Users\xoxo\AppData\Local\Temp\_MEI92882

    C:\Users\xoxo\PycharmProjects\Hentai_Spider>main
    C:\Users\xoxo\AppData\Local\Temp\_MEI92882
    Traceback (most recent call last):
      File "main.py", line 6, in <module>
        from config import args
      File "<frozen importlib._bootstrap>", line 2237, in _find_and_load
      File "<frozen importlib._bootstrap>", line 2226, in _find_and_load_unlocked
      File "<frozen importlib._bootstrap>", line 1200, in _load_unlocked
      File "<frozen importlib._bootstrap>", line 1129, in _exec
      File "C:\Python34\lib\site-packages\PyInstaller\loader\pyimod03_importers.py",
     line 631, in exec_module
        exec(bytecode, module.__dict__)
      File "config.py", line 12, in <module>
        parser.add_argument('-sd', '--savedir', default=config['ARGS']['SAVEDIR'])
      File "configparser.py", line 936, in __getitem__
    KeyError: 'ARGS'
    [9296] Failed to execute script main
    
    C:\Users\xoxo\PycharmProjects\Hentai_Spider>

    6 . 可以看到config.py虽然封装前和main.py在一个文件夹下,但被封装后,执行时就处于临时文件夹,这时候取其自身所在目录的动作就有问题

    解决方案

    main.py来抓目录信息,再传给config.py(中函数)

    教训

    1. 封装程序没有聪明到能理解设计意图,所以写代码的得更聪明点

    2. 如果某项目可能会被封装,让被封装的那个程序来抓取目录信息并传递

关键字