Is there any way to import a Python module in a string?

Viewed 66

Let's say, I have a string defined in code as such:

module_string = """
def add(x, y):
    return x + y

def multiply(x, y):
    return x * y
"""

Is there any way to effectively do the following:

from module_string import add, multiply

According to the Python documentation, a script will only search for modules as .py files in the directory containing the input script (or the current directory when no file is specified)." and then look for a module in the PYTHONPATH or the installation-dependent default.

An obvious method then would be to write the string to a file with suffix .py and then importing it. While this works, it's does create an actual file and a __pycache__ directory in the working directory, which can be undesirable.

While it's possible to use exec() to simply execute the string as code, this does not behave as expected if the module string has an __all__ defined or if there's a if __name__ == '__main__': part of the module that isn't meant to be executed when importing as a module.

Is there any way to get a string to behave like an importable module in Python without necessarily generating a bunch of files and directories in the working directory? Or is it absolutely necessary that a module must exist as a file? Is there some way of faking this via a StringIO object or something similar?


Context: I want to be able to dynamically import a module from a file in a Github Gist and dynamically update the imported classes/functions when the gist undergoes a revision. I am doing this by using GitHub's REST API to read in the Gist as a string via the requests module, but I need to find some way to get this string to be imported as a module within the code itself.

If my question is more of an XY problem instead, I would love to hear other suggestions on how to achieve my intended goal.


PS: Let's assume I have thought through all the various cyber-security issues related to this problem (as I know some people on SO will have the urge to focus on that aspect).

1 Answers

Probably not a great idea to execute code that you download, but if you really want to do it

>>> module_string = """
... def add(x, y):
...     return x + y
... 
... def multiply(x, y):
...     return x * y
... """
>>> exec(module_string)
>>> add(1,2)
3
Related