"AttributeError: '_NotSet' object has no attribute 'lower'" when a PRAW python file is converted to an exe using Pyinstaller

"AttributeError: '_NotSet' object has no attribute 'lower'" when a PRAW python file is converted to an exe using Pyinstaller

正如标题所说。

当我执行转换后的 python 文件(.exe)时,我得到以下输出:

Traceback (most recent call last):
  File "background.py", line 10, in <module>
  File "site-packages\praw\reddit.py", line 129, in __init__
  File "site-packages\praw\config.py", line 72, in __init__
  File "site-packages\praw\config.py", line 98, in _initialize_attributes
  File "site-packages\praw\config.py", line 31, in _config_boolean
AttributeError: '_NotSet' object has no attribute 'lower'
[1692] Failed to execute script background

我没有使用 praw.ini 文件,而是硬编码登录值:

import praw
import praw.models
import urllib.request
from random import randint
from os import getcwd
import ctypes

r = praw.Reddit(client_id='client',
                     client_secret='secret',
                     user_agent='user')
sub = r.subreddit('earthporn')
choose = []
for i in sub.hot(limit=20):
    a = str(i.url)
    if "i.redd" in a or "i.imgur" in a:
        choose.append(i.url)
x = choose[randint(0,len(choose)-1)]
resource = urllib.request.urlopen(x)
output = open("daily_image.jpg","wb")
output.write(resource.read())
output.close()


direc = getcwd() + "\daily_image.jpg"
ctypes.windll.user32.SystemParametersInfoW(20, 0, direc , 0)

以上文件仅在 python 中有效,但在转换为 exe 时无效。 (显然已经设置了客户端、秘密和用户 ID,可以随意窃取它 idrc)

非常感谢任何帮助!

没错。

因此,pyinstaller 不是一个完美的 .py 到 .exe 转换器,因此在转换过程中会丢失一些东西。

我首先注释掉了 praw 中的所有更新,因为这会导致 pyinstaller 创建的 .exe 崩溃(请注意,我在这里所做的一切都会导致 .exe 中的错误,但不会导致 .py 中的错误)。

然后我不得不手动设置一些变量,因为在 .exe 版本中调用它们时没有设置它们。要么在 PRAW 中使用线程,而在 .exe 版本中它跟不上,要么发生了一些非常奇怪的事情。

是的,所以我基本上只是修改了整个 praw 的代码,所以这个东西会 运行。如果有人像我一样遇到这个问题并且无法在任何地方找到答案(因为相信我,我搜索了地球并且找不到它)给我发消息,我可以将我的 praw 版本发给你。

愿上帝保佑你不会出现这个错误

我遇到了这个错误,发现要解决它,您需要在 运行 可执行文件 (your_app.exe) 所在的目录中有一份 praw.ini 的副本。您可以在安装的 \praw 目录中找到 praw.ini

别害怕!代替正确打包的 praw.ini,它包含的配置也可以作为参数显式提供给 Reddit 构造函数:

reddit = praw.Reddit(
    client_id="CHANGEME",
    client_secret="CHANGEME",
    user_agent="CHANGEME",
    check_for_updates=False,
    comment_kind="t1",
    message_kind="t4",
    redditor_kind="t2",
    submission_kind="t3",
    subreddit_kind="t5",
    trophy_kind="t6",
    oauth_url="https://oauth.reddit.com",
    reddit_url="https://www.reddit.com",
    short_url="https://redd.it",
    ratelimit_seconds=5,
    timeout=16,
)

即使在使用 PyInstaller 打包后,上面的代码对我来说也很有效。请注意,未来的 PRAW 更新可能会向 praw.ini 添加更多默认值,因此您必须将它们复制过来,否则您将收到有关未设置配置选项的类似错误。

查看此 GitHub 问题:https://github.com/praw-dev/praw/issues/1016

我无法想象还有人在看这个,但我通过使用 pyinstaller .spec 文件将 praw.ini 添加为数据文件来解决这个问题。我使用的步骤是:

  1. 使用普通 pyinstaller <name>.py 和您喜欢的任何标志(例如 --onefile)创建 .spec 文件。
  2. 通过添加以下内容来修改生成的 .spec 文件:
    import os
    import importlib
    proot = os.path.dirname(importlib.import_module('praw').__file__)
    datas = [(os.path.join(proot, 'praw.ini'), 'praw')]
    
    a = Analysis(['<name>.py'],
                 ...
                 datas=datas,
    
  3. 运行 pyinstaller 针对新编辑的 .spec 文件:pyinstaller <name>.spec