【问题标题】:how to re-invoke python script within itself如何在自身内部重新调用 python 脚本
【发布时间】:2010-05-17 02:58:59
【问题描述】:

我正在尝试找到在其内部重新调用 Python 脚本的最佳方式。目前它的工作方式类似于http://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L285START_CTX 是在 http://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L82-86 创建的。

代码依赖sys.argv[0] 作为“调用者”。但是,在以下情况下会失败:

python script.py ...

这种情况确实有效:

python ./script.py ...

因为代码在运行os.execlp之前使用了os.chdir

我确实注意到了os.environ["_"],但我不确定这有多可靠。另一种可能的情况是检查sys.argv[0] 是否不在PATH 上且不可执行,并在调用os.execlp 时使用sys.executable

对解决此问题的更好方法有什么想法吗?

【问题讨论】:

  • 是否可以简单地不允许第一种情况,或者将脚本包装在可以纠正它的 shell 脚本中?

标签: python


【解决方案1】:

我认为这里真正的问题是 gunicorn/arbiter.py 代码每次都希望在完全相同的环境中执行 Python 脚本。这一点很重要,因为被调用的 Python 脚本是未知的,并且每次都以完全相同的方式调用它很重要。

我的感觉是,您遇到的问题与仲裁程序调用 Python 脚本之间的环境发生变化有关。

  1. http://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L85-89 中,我们看到 python 可执行文件和 args 被仲裁器存储到 self.START_CTX 中。

  2. 然后在http://github.com/benoitc/gunicorn/blob/master/gunicorn/arbiter.py#L303-305 中,我们看到 execvpe 使用 sys.executable、修改后的 args 和 os.environ 调用。

如果 os.environ 在其他地方发生了更改(即 PWD 变量),那么您的可执行文件将无法正确调用(因为您不再位于正确的文件夹中)。仲裁器似乎通过将 cwd 存储在 START_CTX 中来处理这种可能性。所以问题仍然存在,为什么调用会失败?

我尝试了一些测试代码,如下所示:

#!/usr/bin/env python
import sys
import os

def main():
    """Execute twice"""

    cwd = os.getcwd()

    print cwd
    print sys.argv

    if os.path.exists("/tmp/started.txt"):
        os.unlink("/tmp/started.txt")
        print "Deleted /tmp/started.txt"
        print
        return

    args = [sys.executable] + sys.argv[:]
    os.system("touch /tmp/started.txt")
    print "Created /tmp/started.txt"
    print
    os.execvpe(sys.executable, args, os.environ)

if __name__ == '__main__':
    main()

当我从命令行执行这段代码时,它工作得很好:

guest@desktop:~/Python/Test$ python selfreferential.py 
/Users/guest/Python/Test
['selfreferential.py']
Created /tmp/started.txt

/Users/guest/Python/Test
['selfreferential.py']
Deleted /tmp/started.txt

guest@desktop:~/Python/Test$ python ./selfreferential.py 
/Users/guest/Python/Test
['./selfreferential.py']
Created /tmp/started.txt

/Users/guest/Python/Test
['./selfreferential.py']
Deleted /tmp/started.txt

guest@desktop:~/Python/Test$ cd
guest@desktop:~$ python Python/Test/selfreferential.py 
/Users/guest
['Python/Test/selfreferential.py']
Created /tmp/started.txt

/Users/guest
['Python/Test/selfreferential.py']
Deleted /tmp/started.txt

guest@desktop:~$ python /Users/guest/Python/Test/selfreferential.py 
/Users/guest
['/Users/guest/Python/Test/selfreferential.py']
Created /tmp/started.txt

/Users/guest
['/Users/guest/Python/Test/selfreferential.py']
Deleted /tmp/started.txt

guest@desktop:~$ 

如您所见,执行 gunicorn 所做的工作没有问题。所以,也许你的问题与环境变量有关。或者可能与您的操作系统执行事物的方式有关。

【讨论】:

    【解决方案2】:

    我会建议一种不同的方法。将所有脚本功能包装到一个函数中,该函数在脚本执行时被调用,它可以递归调用自身,而不是执行新进程。

    【讨论】:

    • 可以通过多种方式调用 Gunicorn,这意味着它不能强制所有启动序列进入一个阻塞点。
    猜你喜欢
    • 1970-01-01
    • 2010-12-09
    • 2015-05-18
    • 1970-01-01
    • 1970-01-01
    • 2012-06-26
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多