2015-02-09 102 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