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

4

5

As the title says.

When I execute the converted python file (the .exe) I get the following output:

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

I did not use a praw.ini file, instead hardcoding the values for the logon as such:

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)

The above file works in just python but not when converted to an exe. (obviously with the client,secret and user id's set, feel free to steal it idrc)

Any help is really appreciated!

Cornemuse answered 19/4, 2018 at 8:30 Comment(3)
when you run the scripts, it finds and use a praw.ini. (probably from the package itself). Can you place a praw.ininext to you .exe to verify?Eratosthenes
I tried - didn't help. I solved it myself but right now I think I'm about to hit my head very hard against a rockCornemuse
It's likely that module_dir = os.path.dirname(sys.modules[__name__].__file__) in combination with os.path.join(module_dir, 'praw.ini') does not result in a loadable file path. As a result, the system-level praw.ini file isn't loading which has the base settings. A simple solution would be to copy that file into the directory that you execute your program from, that should resolve your issues.Denoting
C
3

Right.

So, pyinstaller isn't a perfect .py to .exe converter, so some things get lost in translation.

I first commented out all updating in praw as this caused a crash in the .exe created by pyinstaller (note everything I did here caused errors in the .exe but never in the .py).

I then had to manually set some variables along the way because they weren't set when they were called in the .exe version. Either threading is used in PRAW and in the .exe version it can't keep up, or there's some seriously weird shit going on.

Yeh so I basically just modified code all throughout praw so this thing would run. If anyone comes across this issue like me and can't find the answer anywhere (because trust me I scoured planet Earth and it's no where to be found) message me and I can send you my praw version.

May god forbid you get this error

Cornemuse answered 19/4, 2018 at 10:11 Comment(2)
I came across this error, just like you. Could you please give your praw version?Summer
Sorry man but this was just under a year ago. I'm on a new system and haven't used PRAW since. However, I do distinctly remember this being especially painful. The only way I could get it to work, was to meticulously go through where the errors occurred, and comment out various bits of code or set values depending on the error. I'm sorry but you're in for a bad time. You could try downgrading python versions though. I know that works for some things.Cornemuse
W
6

I had this error and found that to resolve it you need to have a copy of the praw.ini in the directory where you a running the executable (your_app.exe) from. You can find your praw.ini in your installed \praw directory.

Wilkes answered 1/8, 2019 at 17:17 Comment(1)
Worked for me - just pasted the default from praw.readthedocs.io/en/latest/getting_started/configuration/… into a file praw.ini next to it, worked a charm.Pleuron
C
3

Right.

So, pyinstaller isn't a perfect .py to .exe converter, so some things get lost in translation.

I first commented out all updating in praw as this caused a crash in the .exe created by pyinstaller (note everything I did here caused errors in the .exe but never in the .py).

I then had to manually set some variables along the way because they weren't set when they were called in the .exe version. Either threading is used in PRAW and in the .exe version it can't keep up, or there's some seriously weird shit going on.

Yeh so I basically just modified code all throughout praw so this thing would run. If anyone comes across this issue like me and can't find the answer anywhere (because trust me I scoured planet Earth and it's no where to be found) message me and I can send you my praw version.

May god forbid you get this error

Cornemuse answered 19/4, 2018 at 10:11 Comment(2)
I came across this error, just like you. Could you please give your praw version?Summer
Sorry man but this was just under a year ago. I'm on a new system and haven't used PRAW since. However, I do distinctly remember this being especially painful. The only way I could get it to work, was to meticulously go through where the errors occurred, and comment out various bits of code or set values depending on the error. I'm sorry but you're in for a bad time. You could try downgrading python versions though. I know that works for some things.Cornemuse
G
2

I can't imagine anyone is still looking at this, but I solved this by adding the praw.ini as a data file using a pyinstaller .spec file. The steps I used were:

  1. Create a .spec file by using the normal pyinstaller <name>.py with whatever flags you like (e.g., --onefile).
  2. Modify the generated .spec file by adding the following:
    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. Run pyinstaller against the newly edited .spec file: pyinstaller <name>.spec
Gottwald answered 9/2, 2022 at 19:21 Comment(0)
L
1

Have no fear! In lieu of a properly-packaged praw.ini, the configuration it contains can also be explicitly provided as args to the Reddit constructor:

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,
)

The above code works great for me, even after being packaged with PyInstaller. Note that future PRAW updates may add more defaults to praw.ini, so you'll have to copy them over or you'll get similar errors about unset config options.

See this GitHub issue: https://github.com/praw-dev/praw/issues/1016.

Lanceted answered 26/4, 2021 at 5:17 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.