Reputation: 16870
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
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
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