2

I am trying to load code as a module and then reload the same module but different code programmatically in Python:

import imp

a = """
def test():
    print "Hello from a"
"""

b = """
def test():
    print "Hello from b"
"""


for code in [a, b]:
    with open('user.py', 'wb') as f:
        f.write(code)
    mod = imp.load_source('user', 'user.py')
    getattr(mod, "test")()

Expected output:

Hello from a
Hello from b

Actual output:

Hello from a
Hello from a

Obviously my understanding of how it works is not correct but I can't seem to figure out my mistake.

The only way I could get it to work was if I deleted the generated .pyc file before I wrote the code in the file f. Is there a better way?

the Tin Man
  • 158,662
  • 42
  • 215
  • 303
ducky
  • 1,113
  • 1
  • 11
  • 23

3 Answers3

3

If you're going to be loading code dynamically out of a string or file, best use exec/execfile instead of import. import is meant for files which are static or rarely-changing.

If you still want to use imp.load_source, note the following caveat:

Note that if a properly matching byte-compiled file (with suffix .pyc or .pyo) exists, it will be used instead of parsing the given source file.

"properly matching" means that the compiled file's version matches the interpreter and the timestamp matches. As Tim points out, if you write the file twice in quick succession, the timestamp might not change and the .pyc would still be considered valid.

nneonneo
  • 171,345
  • 36
  • 312
  • 383
  • Note: [This answer](http://stackoverflow.com/a/7548190/307705) explains exactly how to use `exec` to load a module in its own namespace. You can also just load it into the current namespace, but I wouldn't in most cases. – Mu Mind Sep 19 '12 at 06:55
2

Probably not because the timestamp of your .pyc file (accurate to a second) will not be older than the timestamp for your newly written .py file; therefore imp will use the "current" .pyc file unless you delete it first.

Alternatively, you could try waiting for two seconds before reloading the module.

Tim Pietzcker
  • 328,213
  • 58
  • 503
  • 561
  • 2
    Note that with a FAT32 filesystem, you might have to wait longer than 2 seconds due to the granularity of the timestamp. – nneonneo Sep 19 '12 at 06:40
0

Whenever you run or import a python file, module or package, the interpreter will check, if a pyc file exists that matches the version of the py file. If so, it will use the pyc file, otherwise it will compile the py file and overwrite the old pyc file. If the pyc matches the version of the py file is based on file dates. Since you are not saving your file (f), Python does not recognize that it something has changed meantime. So if you want your approach to work, you need to save the file after each loop.

schacki
  • 9,401
  • 5
  • 29
  • 32