0

I run my Python script with

python3.7 -m opencryptobot.START -lvl 20

opencryptobot is a folder here and START is a module. At some point I'd like to restart the script with this code:

os.execl(sys.executable, sys.executable, *sys.argv)

I use this code because it worked perfectly for my other scripts that I don't execute with the -m argument. So the above code will be executed at some point and then I get this error:

ModuleNotFoundError: No module named 'opencryptobot'

Which sounds correct since opencryptobot is just a folder and not a module. I played around with various versions of os.exec to see if I’m able to restart it but nothing really works.

So my question is, how can I restart my script if I run it the way I do?

This is a minimal version of my folder structure:

.
├── LICENSE
├── Pipfile
├── Pipfile.lock
├── README.md
├── opencryptobot
│   ├── START.py
│   ├── config.py
│   ├── constants.py
│   ├── database.py
│   ├── emoji.py
│   ├── plugin.py
│   ├── plugins
│   │   ├── about.py
│   │   ├── admin.py
│   │   └── alltimehigh.py
│   ├── ratelimit.py
│   ├── telegrambot.py
│   └── utils.py
└── start.sh

I execute START from the root folder.

0

1 Answer 1

3

sys.argv does not start with -m opencryptobot.START. The module name is removed from the sys.argv list altogether while resolving the opencryptobot.START module filename (sys.argv is set to ['-m', '-lvl', '20'] until there is a filename) and then '-m' is replaced with the full filename of the module.

From the -m switch documentation:

If this option is given, the first element of sys.argv will be the full path to the module file (while the module file is being located, the first element will be set to "-m").

In effect, Python is simulating running a script, as if you ran python /path/to/opencrytobot/START.py ...; only the __package__ context is kept so you can still use package-relative imports such as from . import ....

So to recreate your original command-line, use '-m', __spec__.name, *sys.argv[1:] as the argument list beyond sys.executable:

os.execl(sys.executable, sys.executable, '-m', __spec__.name, *sys.argv[1:])

You can't use __name__, unfortunately, as that has been set to '__main__' when using -m. However, the __spec__ object set on your module does know what the full qualified name is for the current module, so we can re-use that here.

Note that even though there is no __init__.py file in opencryptobot, by using -m you are telling Python that opencryptobot is really an implicit namespace package. If that wasn't the intention here, then don't use -m to load your script.

Demo:

$ ls -1 opencryptobot/
START.py
$ cat opencryptobot/START.py
import sys
import os

if __name__ == '__main__':
    print('Running as the __main__ script')
    print('sys.argv:', sys.argv)
    print('__spec__.name:', __spec__.name)

    if 'restarted' not in sys.argv:
        print('Respawning:')
        # add an extra command-line option to stop respawning a second time
        os.execl(sys.executable, sys.executable, '-m', __spec__.name, *sys.argv[1:], 'restarted')
$ python3.7 -m opencryptobot.START -lvl 20
Running as the __main__ script
sys.argv: ['/.../opencryptobot/START.py', '-lvl', '20']
__spec__.name: opencryptobot.START
Respawning:
Running as the __main__ script
sys.argv: ['/.../opencryptobot/START.py', '-lvl', '20', 'restarted']
__spec__.name: opencryptobot.START
Sign up to request clarification or add additional context in comments.

11 Comments

Thanks for this Martijn and sorry for wasting your time with this but it doesn't work. There is no error but the script will not be started again. The script just exits and i'm back at the command line.
@Endogen: we already have a weird situation here, as your claim that START is a class, not a module. Can you please, in your question, add a clear illustration of what files you have and minimal contents of those files to help me reproduce your issue here?
@Endogen: I have no issue making this work with START.py being a file inside an otherwise empty opencryptobot directory (Python 3 treats that as a namespace package, you shouldn't really use it that way).
Ah ok, so it works if i add the Python extension? I will try that. Please see the link in my edited question for the current folder structure
@Endogen: no, put that tree in your question, and make it a minimal example.
|

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.