Search code examples
pythoninterfacecommand-line-interfaceexecfile

Updating Python CLI while maintaining "python -c exectfile" interface


I have a number of scripts that reference a Python program via the:

python -c "execfile('myfile.py'); readFunc(param='myParam', input='blahblah')"

interface. What I'd like to do is conceptually simple: Develop a more modular system with a "main" and a normal Python CLI interface that then calls these functions, but also MAINTAINS the existing interface, so the scripts built to use it still work.

Is this possible?

Ideally, if I was to call

python myFile readFunc myParam blabblah

It'd be something like:

main(sys.argv):
     readFunc(sys.argv[2], sys.arg[3])

I've tried something like that, but it hasn't quite worked. Is it possible to keep both interfaces/methods of invocation?

Thanks!


Solution

  • The first idea that comes to mind stems from the optional arguments to the execfile() function. You might be able to do something like this:

    #!python
    def main(args):
        results = do_stuff()
        return results
    
    if __name__ == '__main__':
        import sys
        main(sys.argv[1:])
    
    if __name__ == 'execfile':
        main(args)
    

    ... and then when you want to call it via execfile() you supply a dictionary for its optional globals argument:

    #!sh
    python -c 'execfile(myfile, {"__name__":"execfile", "args":(1,2,3)}); ...'
    

    This does require a little extra work when you're calling your functionality via -c as you have to remember to pass that dictionary and over-ride '__name__' ... through I suppose you could actually use any valid Python identifier. It's just that __name__ is closest to what you're actually doing.

    The next idea feels a little dirty but relies on the apparent handling of the __file__ global identifier. That seems to be unset when calling python -c and set if the file is being imported or executed. So this works (at least for CPython 2.7.9):

    #!/usr/bin/env python
    foo='foo'
    if __name__ == '__main__' and '__file__' not in globals():
        print "Under -c:", foo
    
    elif __name__ == '__main__':
        print "Executed standalone:", foo
    

    ... and if you use that please don't give me credit. It looks ...

    ... ... ummm ....

    ... just ...

    .... WRONG