Как получить полные параметры командной строки argv интерпретатора Python?

Как мы знаем из документации:

-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 неверен, потому что он не работает в угловом случае.


person Mihail Krivushin    schedule 09.02.2015    source источник


Ответы (1)


Если я запущу сервер разработки werkzeug, то он потеряет опцию -c cmd на форке.

Во-первых, процесс не просто разветвляется. Вызывается новый интерпретатор Python.

Что вы имеете в виду под it will lost -c cmd? Тот факт, что строка cmd пропала в argv? То есть:

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

Действительно, строка cmd недоступна из sys.argv. Это соответствующая документация:

Если команда была выполнена с использованием параметра командной строки -c для интерпретатора, argv[0] устанавливается в строку '-c'

Документы не комментируют фактическую командную строку. Хотя эта командная строка была явно «отправлена» в качестве аргумента исполняемому файлу интерпретатора Python, реализация CPython, похоже, не предоставляет эту информацию в sys.argv. Я предполагаю, что невозможно восстановить эту информацию без изменения исходного кода sysmodule.c. Так что, если вы думаете, что зависите от извлечения cmd, вы не должны этого делать! Вам нужно найти другой способ ввести эту информацию.

Изменить:

Фактическая командная строка используется в Modules/main.c в функции Py_Main():

wcscpy(command, _PyOS_optarg);

Это command выполняется позже в main.c.

Аргументы командной строки обрабатываются через PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);, который, в свою очередь, вызывает makeargvobject() в sysmodule.c. Последняя функция переводит данные двоичного аргумента в объекты Unicode Python (по крайней мере, в Python 3) в цикле, подобном for (i = 0; i < argc; i++) {}. Таким образом, 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";
}

Изменить2:

Подтверждена решающая роль _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)']
person Dr. Jan-Philip Gehrcke    schedule 09.02.2015
comment
Благодарю вас! Не нашел где 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'] - person Mihail Krivushin; 10.02.2015