I am trying to dynamically add python code to a sandbox module for executing on a remote machine. I am experiencing an issue with how to deal with imported methods. For example, it is common to see scripts written such as:
from test_module import g
import other_module
def f():
g()
other_module.z()
I know I can pickle f with g and potentially z but how do I preserve the "other_module" scope for z? If I put both f and g in the sandbox then z is not going to be resolved properly when f is called. Is it possible to use some type of embedded module to get z resolved correctly, i.e. sandbox.other_module?
My purpose for loading remote code into a sandbox is to not pollute the global namespace. For instance, if another remote method is invoked with it's own dependency graph then it should not interfere with another set of remote code. Is it realistic to expect python to be stable with sandbox modules coming in and out of usage? I say this because of this post: How do I unload (reload) a Python module? which makes me feel it can be problematic removing modules such as different sandboxes in this case.
Current approach I have going for enabling both 'import x' and 'from x import y' dependency bundling. One draw back, to this current implementation, is it creates copies of the methods in each module that is used, in contrast to the code origin where each usage is just a reference to the same method in memory (though I have conflicting results here - see section after code).
/// analysis_script.py /// (dependencies excluded for brevity)
/// driver.py ///
/// modutil.py ///
/// sandbox_reader.py ///
For instance the function graph looks like this before serialization:
Specifically, looking at the function z we can see that all the references point to the same address, i.e. 0x7f47d719ade8.
On the remote process after sandbox reconstruction we have:
This blows my mind! I would have thought all addresses here would be unique after reconstruction but for some reason sandbox_module.test_module.z and sandbox_module.third_level_module.z have the same address?
Other modules can be imported to sandbox (you mean modules that are created dynamically at runtime) by
or:
If you call "sandbox" modules from other modules or other sandbox modules and you want to reload some new code later, it is easier to import only a module, not names from it like "from sandbox import f", and call "sandbox.f" not "f". Then is reloading easy. (but naturarely reload command is not useful for it)
Classes
It seems that reloading methods can be easy. I remember that reloading classes defined in a modified source code can be complicated because the old class code can be held by some instance. The instance's code can/need be updated individually in the worst case:
I used the latter with a python service accessed via win32com automation and reloading of classes code was succesful without loss instances data
<module_name> <serialized_func1> <serialized_func2>...
is not general enough. A function can be on the local machine imported under different names by "... import ... as ..." clause. You can serialize list of tuples of mixed strings and code objects.Hint
Now is no important difference between sandbox and other serialized module. Conditions "if sandbox" can be soon removed.