如何获得python interpreter完整的argv命令行选项?

时间:2015-02-09 15:10:20

标签: python argv werkzeug

正如我们从文档中所知:

  

-c   如果给出了这个选项,sys.argv的第一个元素将是" -c"并且当前目录将被添加到sys.path的开头(允许将该目录中的模块导入为顶级模块)。

如何获得完整的解释器命令行选项?我需要它来解决这个问题:

https://github.com/mitsuhiko/werkzeug/blob/f50bdc04cf1c8d71d12d13a0c8ef2878477f4d24/werkzeug/_reloader.py#L141

如果我启动werkzeug开发服务器,那么它将在fork上丢失-c cmd选项。我想修补werkzeug,但无法找到如何获得真正的选择。

如果你想知道为什么我需要这个 - 我想在manage.py之前预先执行一些想要解析sys.argv的代码。而且我认为werkzeug方法不正确,因为它不适用于极端情况。

1 个答案:

答案 0 :(得分:2)

  

如果我启动werkzeug开发服务器,那么它将丢失-c cmd   叉上的选项。

首先,这个过程不是简单的分叉。调用了一个新的Python解释器。

it will lost -c cmd你是什么意思? argv中cmd字符串消失的事实?那就是:

$ python -c "import sys; print(sys.argv)"
['-c']

实际上,无法从cmd内访问sys.argv字符串。 This是相关文档:

  

如果使用-c命令行选项执行命令   解释器,argv [0]设置为字符串'-c'

文档不会对实际命令字符串发表评论。虽然该命令字符串明确地“发送”为Python解释器exectuable的参数,但CPython实现似乎并未在sys.argv中公开此信息。我想如果不改变sysmodule.c的源代码,就无法重建这些信息。所以,如果你认为你依赖于提取cmd - 你不应该!您需要找到另一种方法来注入这些信息。

修改

实际命令字符串在函数Py_Main()中的Modules/main.c中使用:

wcscpy(command, _PyOS_optarg);

commandmain.c中稍后执行的内容。

命令行参数通过PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);处理,makeargvobject()依次调用sysmodule.c中的for (i = 0; i < argc; i++) {}。后一个函数将二进制参数数据转换为类似argc的循环中的Python unicode对象(至少在Python 3中)。因此,_PyOS_optind必须(故意)偏离-1才能忽略所述循环中的命令。

也就是说,删除命令参数的神奇之处在于设置PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);,以便后续调用if (command != NULL) { /* Backup _PyOS_optind and force sys.argv[0] = '-c' */ _PyOS_optind--; argv[_PyOS_optind] = L"-c"; } 表明参数计数小于(实际为1)。

我没有真正遵循,但我猜这些行的减少是负责任的:

_PyOS_optind

<强> EDIT2:

使用以下补丁验证diff --git a/Modules/main.c b/Modules/main.c --- a/Modules/main.c +++ b/Modules/main.c @@ -679,9 +679,11 @@ } if (command != NULL) { /* Backup _PyOS_optind and force sys.argv[0] = '-c' */ _PyOS_optind--; - argv[_PyOS_optind] = L"-c"; + _PyOS_optind = 0; + //argv[_PyOS_optind] = L"-c"; } if (module != NULL) { 的关键作用,以及当前的Python 3提示:

 $ ./python -c "import sys; print(sys.argv)"
['./python', '-c', 'import sys; print(sys.argv)']

测试:

{{1}}