2015-02-09 67 views
1

我们知道从文档:如何获得python解释器完整的argv命令行选项?

-c 如果这个选项,则sys.argv中的第一个元素将是“-c”和当前目录将被添加到sys.path中开始(允许将该目录中的模块作为顶级模块导入)。

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

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

如果我开始WERKZEUG开发服务器,那么它将失去叉-c cmd选项。我想补丁werkzeug,但不能找到如何得到真正的选择。

如果你想知道为什么我需要这个 - 我想先在manage.py之前预先执行一些代码,然后再解析sys.argv。而且我认为werkzeug方法是不正确的,因为它不在角落情况下工作。

回答

2

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

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

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

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

事实上,cmd字符串不是从sys.argv中访问。 This是相关文档:

如果是使用-c命令行选项的 解释器执行的命令,argv的[0]被设定为字符串“-c”

该文档做没有评论实际的命令字符串。尽管该命令字符串被明确“发送”为Python解释器可执行文件的参数,但CPython实现似乎并未在sys.argv中公开此信息。我想没有办法在不更改sysmodule.c的源代码的情况下重构此信息。所以,如果你认为你依靠提取cmd - 你不应该!你需要找到另一种方式来注入这些信息。

编辑:

实际的命令字符串在Modules/main.c消耗功能Py_Main()

wcscpy(command, _PyOS_optarg); 

commandmain.c正在执行以后什么。

命令行参数通过PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);进行处理,后者又调用sysmodule.c中的makeargvobject()。后者函数将二进制参数数据翻译成类似for (i = 0; i < argc; i++) {}的循环中的Python unicode对象(至少在Python 3中)。所以,argc必须(有意)被-1关闭,以便忽略所述循环中的命令。

也就是说,丢弃命令参数的魔力在于设置_PyOS_optind,因此后续调用PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);表明参数计数比实际值小(1)。

我并没有真正贯彻,但我想在这行递减负责:

if (command != NULL) { 
    /* Backup _PyOS_optind and force sys.argv[0] = '-c' */ 
    _PyOS_optind--; 
    argv[_PyOS_optind] = L"-c"; 
} 

EDIT2:

验证的_PyOS_optind这里的关键作用,用下面的补丁,当前Python 3提示:

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 -c "import sys; print(sys.argv)" 
['./python', '-c', 'import sys; print(sys.argv)'] 
+1

谢谢!没有找到“cmd”真的有条纹的地方。在这个文件中我找到了Py_GetArgcArgv! 然后我尝试了一些奇怪的工作人员,像这样奇怪的结果: '>>> python -c'import ctypes; argv = ctypes.POINTER(ctypes.c_char_p)(); argc = ctypes.c_int(); ctypes.pythonapi.Py_GetArgcArgv(ctypes.byref(argc),ctypes.byref(argv)); print([argv [i] for i in xrange(0,argc.value)])'' '['python','-c','-c']' – 2015-02-10 09:01:40