Search code examples
pythonpython-import

Making Python run a few lines before my script


I need to run a script foo.py, but I need to also insert some debugging lines to run before the code in foo.py. Currently I just put those lines in foo.py and I'm careful not to commit that to Git, but I don't like this solution.

What I want is a separate file bar.py that I don't commit to Git. Then I want to run:

python /somewhere/bar.py /somewhere_else/foo.py

What I want this to do is first run some lines of code in bar.py, and then run foo.py as __main__. It should be in the same process that the bar.py lines ran in, otherwise the debugging lines won't help.

Is there a way to make bar.py do this?

Someone suggested this:

import imp
import sys

# Debugging code here

fp, pathname, description = imp.find_module(sys.argv[1])
imp.load_module('__main__', fp, pathname, description)

The problem with that is that because it uses import machinery, I need to be on the same folder as foo.py to run that. I don't want that. I want to simply put in the full path to foo.py.

Also: The solution needs to work with .pyc files as well.


Solution

  • Python has a mechanism for running code at startup; the site module.

    "This module is automatically imported during initialization."
    

    The site module will attempt to import a module named sitecustomize before __main__ is imported. It will also attempt to import a module named usercustomize if your environment instructs it to.

    For example, you could put a sitecustomize.py file in your site-packages folder that contains this:

    import imp
    
    import os
    
    if 'MY_STARTUP_FILE' in os.environ:
        try:
            file_path = os.environ['MY_STARTUP_FILE']
            folder, file_name = os.path.split(file_path)
            module_name, _ = os.path.splitext(file_name)
            fp, pathname, description = imp.find_module(module_name, [folder])
        except Exception as e:
            # Broad exception handling since sitecustomize exceptions are ignored
            print "There was a problem finding startup file", file_path
            print repr(e)
            exit()
    
        try:
            imp.load_module(module_name, fp, pathname, description)
        except Exception as e:
            print "There was a problem loading startup file: ", file_path
            print repr(e)
            exit()
        finally:
            # "the caller is responsible for closing the file argument" from imp docs
            if fp:
                fp.close()
    

    Then you could run your script like this:

    MY_STARTUP_FILE=/somewhere/bar.py python /somewhere_else/foo.py
    
    • You could run any script before foo.py without needing to add code to reimport __main__.
    • Run export MY_STARTUP_FILE=/somewhere/bar.py and not need to reference it every time