azmeuk
azmeuk

Reputation: 4506

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?

Upvotes: 0

Views: 285

Answers (2)

Gribouillis
Gribouillis

Reputation: 2220

I think the negative value of limit does not work in traceback module before python 3.5. Here is an ugly hack that works with python 2.7

import sys
import traceback

class ExcFile(object):
    def __init__(self, file):
        self.topline = True
        self.file = file

    def write(self, s):
        if self.topline:
            u, s = s.split('\n', 1)
            self.file.write(u +'\n')
            self.topline = False
        if '#---\n' in s:
            u, s = s.split('#---\n', 1)
            self.file.write(s)
            self.write = self.file.write

ExcFile._instance = ExcFile(sys.stdout)    
# The following block of code removes the part of 
# the traceback related to this very module, and runpy
def myexcepthook(type, value, tb):
    traceback.print_exception(type, value, tb, file=ExcFile._instance)
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) #---

All this should be written in a separate file, to avoid clutter __main__.py.

Upvotes: 1

azmeuk
azmeuk

Reputation: 4506

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!

Upvotes: 1

Related Questions