我使用以下命令运行Python脚本
python3.7 -m opencryptobot.START -lvl 20
opencryptobot
是这里的文件夹,而START
是模块。在某些时候,我想使用以下代码重新启动脚本:
os.execl(sys.executable, sys.executable, *sys.argv)
我之所以使用此代码,是因为它可以完美地用于我的其他脚本中,这些脚本无需使用-m
参数即可执行。所以上面的代码将在某个时候执行,然后我得到这个错误:
ModuleNotFoundError: No module named 'opencryptobot'
这听起来是正确的,因为opencryptobot
只是一个文件夹,而不是一个模块。我试用了os.exec
的各种版本,以查看是否可以重新启动它,但实际上没有任何作用。
所以我的问题是,如果我以自己的方式运行脚本,如何重新启动脚本?
这是我的文件夹结构的最低版本:
.
├── 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
我从根文件夹执行START
。
答案 0 :(得分:3)
sys.argv
不以-m opencryptobot.START
开头。在解析sys.argv
模块文件名(将opencryptobot.START
设置为sys.argv
直到有文件名)时,将模块名称从['-m', '-lvl', '20']
列表中完全删除。 }替换为模块的完整文件名。
如果提供了此选项,则
'-m'
的第一个元素将是模块文件的完整路径(在查找模块文件时,第一个元素将被设置为sys.argv
)。
实际上,Python正在模拟运行脚本,就像您运行了"-m"
一样;仅保留python /path/to/opencrytobot/START.py ...
上下文,因此您仍可以使用相对于软件包的导入,例如__package__
。
因此要重新创建您的原始命令行,请使用from . import ...
作为'-m', __spec__.name, *sys.argv[1:]
之外的参数列表:
sys.executable
很遗憾,您无法使用os.execl(sys.executable, sys.executable, '-m', __spec__.name, *sys.argv[1:])
,因为在使用__name__
时已将其设置为'__main__'
。但是,__spec__
object set on your module确实知道当前模块的标准名称是什么,因此我们可以在此处重复使用。
请注意,即使-m
中没有__init__.py
文件,通过使用opencryptobot
也是在告诉Python -m
实际上是implicit namespace package。如果这不是这里的意图,那么不要使用opencryptobot
来加载脚本。
演示:
-m