Skip to content Skip to sidebar Skip to footer

How To Get Python Interpreter Full Argv Command Line Options?

As we know from documentation: -c If this option is given, the first element of sys.argv will be '-c' and the current directory will be added to the start of sys.path (allowing

Solution 1:

If I start werkzeug development server, then it will lost -c cmd option on fork.

First of all, the process is not simply forked. A fresh Python interpreter is invoked.

What do you mean with it will lost -c cmd? The fact that the cmd string is gone in argv? That is:

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

Indeed, the cmd string is not accessible from within sys.argv. This is related documentation:

If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'

The docs do not comment on the actual command string. While that command string was clearly "sent" as an argument to the Python interpreter exectuable, the CPython implementation does not seem to expose this information within sys.argv. I guess there is no way to reconstruct this information without changing the source code of sysmodule.c. So, if you think you depend on extracting cmd -- you shouldn't! You need to find another way to inject this information.

Edit:

The actual command string is consumed in Modules/main.c in function Py_Main():

wcscpy(command, _PyOS_optarg);

This command is what is being executed later on in main.c.

The command line arguments are processed via PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind);, which in turn calls makeargvobject() in sysmodule.c. The latter function translates the binary argument data into Python unicode objects (at least in Python 3 it does) in a for (i = 0; i < argc; i++) {}-like loop. So, argc must (purposely) be off by -1 in order to ignore the command in said loop.

That is, the magic of dropping the command argument is in setting _PyOS_optind, so that the subsequent call to PySys_SetArgv(argc-_PyOS_optind, argv+_PyOS_optind); suggests an argument count smaller (by 1) than it actually is.

I did not really follow through, but I guess the decrement in these lines is responsible:

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

Edit2:

Verified the crucial role of _PyOS_optind here with the following patch to the current Python 3 tip:

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) {

Test:

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

Post a Comment for "How To Get Python Interpreter Full Argv Command Line Options?"