user9935865
user9935865

Reputation:

python import a module with source code in temporary file

import tempfile

tmp = tempfile.NamedTemporaryFile(delete=True)
try:
    # do stuff with temp
    tmp.write(b'def fun():\n\tprint("hello world!")\n')
    if __name__ == '__main__':
        func = __import__(tmp.name)
        func.fun()
finally:
    tmp.close()  # deletes the file

So I want to create a temporary file, add some source code to it and then import the module and call the function, but I always run into this error:

ModuleNotFoundError: No module named '/var/folders/3w/yyp887lx4018h9s5sr0bwhkw0000gn/T/tmp84bk0bic'

It doesn't seem to find the module of the temporary file. How do I solve this?

Upvotes: 2

Views: 4640

Answers (2)

Alfe
Alfe

Reputation: 59566

Importing can only be done from certain directories which are part of the PYTHON_PATH. You can extend that. Then you will have to use __import__() with a module name (not a path in the file system). You will have to deal with the suffix for the temp file.

I implemented a simple version using the local directory for the temp module file and a version using a proper tempfile:

#!/usr/bin/env python3

import sys
import os
import tempfile

SCRIPT = '''\
def fun():
  print("hello world!")
'''

# simple version using the local directory:
with open('bla.py', 'w') as tmp_module_file:
  tmp_module_file.write(SCRIPT)
import bla
bla.fun()

# version using the tempfile module:    
tmpfile = tempfile.NamedTemporaryFile(suffix='.py', delete=True)
try:
  tmpfile.write(SCRIPT.encode('utf8'))
  tmpfile.flush()
  tmpmodule_path, tmpmodule_file_name = os.path.split(tmpfile.name)
  tmpmodule_name = tmpmodule_file_name[:-3]  # strip off the '.py'
  sys.path.append(tmpmodule_path)
  tmpmodule = __import__(tmpmodule_name)
finally:
  tmpfile.close()
tmpmodule.fun()

Upvotes: 1

John Zwinck
John Zwinck

Reputation: 249542

There are a few problems with your code:

  1. Your filename does not end with .py, but Python modules are expected to. You can fix this by setting suffix='.py' in NamedTemporaryFile().
  2. __import__() is not the right way to load a module from a full path. See here: How to import a module given the full path?
  3. You do not flush after writing and before importing, so even if Python does find the file, it may well be empty. Add tmp.flush() after writing to fix this.

Upvotes: 4

Related Questions