Niklas R
Niklas R

Reputation: 16870

Load Python source/binary without adding to sys.modules

I want to load Python code (if possible with an arbitrary file-extension or even from memory, source or binary) without adding it to sys.modules. Using imp.load_source works for loading a file but the returned module is added to sys.modules and might even be joined with an existing module (see this question)!

So, what I'm currently doing is using the __import__() built-in. Although it allows me to import from a package, I can not load an arbitrary file.

try:
    m = __import__(name)
    for n in name.split('.')[1:]:
        m = getattr(m, n)
    return m
except:
    raise
finally:
    # Restore the old module configuration. Only modules that have
    # not been in sys.path before will be removed.
    for k, v in sys.modules.items():
        if k not in prev_modules and self.is_local(v) or not v:
            del sys.modules[k]
        else:
            sys.modules[k] = v
  1. Removing all modules that haven't been in before the import is a very hacky approach to me.
  2. When a module with the name already exists, it is not reloaded.
  3. I can not load an arbitrary file or even from memory.

I am trying to avoid the exec statement because of security reasons. The source evaluated by exec could hack in to my application using sys._getframe() (and there sure are many more possibilities to do). I have looked at the implementation of the django load tag, but that just uses __import_() as well.

Is there a way to load Python code (either source or binary) from a file (or even memory) that is secure, self-contained (no adding interaction with sys.modules)? In the best case, it would not only allow me to load a file and from memory, but also load a complete package like the __import__() function.

Upvotes: 2

Views: 355

Answers (1)

jeffknupp
jeffknupp

Reputation: 6274

Using the CPython interpreter, I don't believe this is possible. However, PyPy provides a sandboxed environment that makes what you want to do quite easy.

Look at the PyPy documentation on sandboxing for details.

Upvotes: 1

Related Questions