Search code examples
pythonmodulepython-moduleargv

How to load a python module with arguments in python?


I would like to create a python module that would be called with python -m mymodule somefile.py some_arg some_arg.

The idea is that I would be able to set up an alias alias="python -m mymodule" and call files normally with python somefile.py some_arg some_arg.

In the file mymodule/__main__.py, what is the best way to load somefile.py and pass it the argument list?

  • I am looking for a generic solution, that would be python2 and 3 compatible.
  • It would be great to be as little intrusive as possible. If somefile.py would raise an exception, mymodule should barely be seen in the traceback.
  • What the module does is not interesting here in detail, but it sets up some python things (traceback hooks etc.), so somefile.py should be ran pythonicly in the same process. os.system or subprocess.Popen do not fit.

Solution

  • Ok I found something good for python 3.5, and satisfying enough for python 2.7.

    mymodule/main.py

    import sys
    
    # The following block of code removes the part of 
    # the traceback related to this very module, and runpy
    # Negative limit support came with python 3.5, so it will not work
    # with previous versions.
    # https://docs.python.org/3.5/library/traceback.html#traceback.print_tb
    def myexcepthook(type, value, tb):
         nb_noise_lines = 3
         traceback_size = len(traceback.extract_tb(tb))
         traceback.print_tb(tb, nb_noise_lines - traceback_size)
    if sys.version_info >= (3, 5):
        sys.excepthook = myexcepthook
    
    if len(sys.argv) > 1:
        file = sys.argv[1]
        sys.argv = sys.argv[1:]
    
        with open(file) as f:
             code = compile(f.read(), file, 'exec')
             exec(code)
    

    somefile.py

    import sys
    print sys.argv
    raise Exception()
    

    in the terminal

    $ python3 -m mymodule somefile.py some_arg some_arg
    ['somefile.py', 'some_arg', 'some_arg']
    Traceback (most recent call last):
      File "somefile.py", line 3, in <module>
        raise Exception()
    
    $ python2 -m mymodule somefile.py some_arg some_arg
    ['somefile.py', 'some_arg', 'some_arg']
    Traceback (most recent call last):
      File "/usr/lib64/python3.5/runpy.py", line 184, in _run_module_as_main
        "__main__", mod_spec)
      File "/usr/lib64/python3.5/runpy.py", line 85, in _run_code
        exec(code, run_globals)
      File "/home/azmeuk/dev/testpy/mymodule/__main__.py", line 16, in <module>
        exec(code)
      File "somefile.py", line 3, in <module>
        raise Exception()
    
    $ python somefile.py some_arg some_arg
    ['somefile.py', 'some_arg', 'some_arg']
    Traceback (most recent call last):
      File "somefile.py", line 3, in <module>
        raise Exception()
    Exception
    

    Still, if someone has a better proposition, it would be great!