Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

sys.argv behavior with python -m

question about __init__.py behavior in python 3.5.2. I've noticed that "sys.argv" and "import __main__" behave differently depending on when their called. For example:

$ tree 
└── subdir
    ├── __init__.py : "import sys; print(sys.argv)"
    ├── __main__.py : "import sys; print(sys.argv)"

$ python -m subdir
['-m']
['/path/to/code/subdir/__main__.py']

Here I'm caught off guard as I'd expect sys.argv to be the same throughout a processes lifetime. I have an intuition as to why this happens but I'm wondering if there is any way of knowing at import time what the true sys.argv is in the __init__.py module.

For reference it looks like argv is altered in Lib/runpy.py@_run_module_as_main

like image 621
Buck Avatar asked Oct 30 '22 12:10

Buck


1 Answers

Short Version: there is no way to find __main__ before it is run

Long Version:

  • the -m flag causes sys.argv[0] to be manipulated
  • the problem is in the timing with which sys.argv is manipulated
    • main.c@Py_main does some flag parsing and pops off the module name to call
    • main.c@RunModule a wrapper around runpy.py@_run_module_as_main
    • _run_module_as_main sets the sys.argv[0] but does not do so until after calling runpy.py@_get_main_module_details
      • a side effect in _get_module_details actually imports the package and its ancestors which executes the __init__.py script before _get_main_module_details can resolve thus _run_module_as_main can't set sys.argv

I think this could be refactored such that sys.argv is set before _get_module_details imports the package and ancestors (I think made possible by module specs) but will have to wait for an enhancement to the runpy architecture, possibly in the form of this which was in the works as of late last year.

like image 111
Buck Avatar answered Nov 15 '22 05:11

Buck