Russell Teapot
Russell Teapot

Reputation: 523

Extend the functionality of a compiled Python script

I'm not a programmer, so I don't even know in what terms should I ask this. Let's say I've compiled a Python script to have an .exe (I use py2exe to do this). This is the major program. Now, I want to add some extra functionality to it, but I don't want to recompile the entire script with the added functionality. I tried to search something on the web, and I found examples of extending a C++ or other application with Python scripts (like a sort of plugin). But I can't figure out how to do it with an application already written in Python.

I tried this: I wrote major.py (this is the script from where I build the executable) and stuff.py. In major I wrote this:

def generic():
    import stuff
    while True:
        param=input('what did you say? ')
        stuff.speak(param)

generic()

And in stuff I wrote this:

def speak(param):
    print(param)

Then I created a .exe with py2exe. It works as expected, when I run the program in the command line says "what did you say?" and waits until I type something, then it prints what I typed. Then, I changed stuff.py with this:

def speak(param):
    print('I said '+param)

Hoping that now upon the execution of the .exe created earlier it would print "I said.." plus whatever I typed. Obviously, it didn't work, the program continued to behave like before. So I'm guessing that once I imported stuff and created the .exe file, that import is permanent, not allowing me to change whatever is in stuff. What should I do?

Upvotes: 1

Views: 446

Answers (3)

mementum
mementum

Reputation: 3203

py2exe packs the compiled scripts in the executable.

You need to recreate the executable (which will recompile any changed script) to see the changes take effect.

EDIT following the comments: You can do it if you dynamically import/reimport the module from inside the executable.

In your main script you do (see code below)

mod, error = loadmodule('mystuff.py')

if mod is not None:
    # loading succeeded you can now proceed and do things with it
    pass

Of course you have to leave mystuff.py out of the scripts that py2exe packs into the executable. In the above example mystuff.py would be in the same directory as the executable.

The loading code:

def loadmodule(modpath, modname=''):

    if not modpath.endswith('.py'):
        modpath += '.py'

    # generate a random name for the module
    if not modname:
        modpathbase = os.path.basename(modpath)
        modname, _ = os.path.splitext(modpathbase)

    version = (sys.version_info[0], sys.version_info[1])

    if version < (3, 3):
        mod, e = loadmodule2(modpath, modname)
    else:
        mod, e = loadmodule3(modpath, modname)

    return mod, e


def loadmodule2(modpath, modname):
    import imp

    try:
        mod = imp.load_source(modname, modpath)
    except Exception as e:
        return (None, e)

    return (mod, None)


def loadmodule3(modpath, modname):
    import importlib.machinery

    try:
        loader = importlib.machinery.SourceFileLoader(modname, modpath)
        mod = loader.load_module()
    except Exception as e:
        return (None, e)

    return (mod, None)

Upvotes: 3

Mr. E
Mr. E

Reputation: 2120

There is no way to do what you want. py2exe builds a standalone python interpreter (In the file named python.dll) with just the dependencies of your project. Then the .exe file runs your script using that interpreter

I suggest you that if you really need to provide regular upgrades then you should recompile it, or install python in the target machine, or make an updating routine that checks for updates and compiles it in the target machine (With py2exe)

Upvotes: 1

mattc
mattc

Reputation: 495

If you run your script from Python, instead of compiling it as an executable, you can make changes and run them without having to recompile. The py2exe is mostly for allowing you to distribute your application to other Windows computers that don't have Python installed. After you have finished developing it, then compile it as an executable so you can run it on other computers.

Upvotes: 1

Related Questions