1

I have a text string, code, containing the complete code for a python module. I know I could write the code to a local file and import it as cm with the following:

with open("codemod.py","w") as f:
    f.write(code)
import codemod as cm

Is there a way do this directly from the code string without creating a local file? Perhaps using importlib or __import()__ or exec()?

I know that exec(code) has the same effect as import codemod, but how do I mimic the import as cm option?

holistone
  • 63
  • 3

2 Answers2

1

You can use exec to execute the code in the string:

# Read file
with open('codemod.py', 'r') as f: 
    code = f.read()

# Execute code
exec(code)

However, as you've already noticed, this will be running the code in the current namespace and not import it as a module but simply execute it. If you want to have the code to be imported as a module, you need to create the module by hand and add it to the current namespace yourself:

# Read file
with open('codemod.py', 'r') as f: 
    code = f.read()

import importlib.util as importutil

# Name of module

# Create a new spec for our module
codemod_spec = importutil.spec_from_loader("codemod", loader=None)

# Create a new module codemod
codemod_module = importlib.utils.module_from_spec(codemod_spec)

# Execute the code in the codemod's namespace
exec(code, codemod_module)

# Add module to namespace as 'cm' instead of 'codemod'
globals()['cm'] = codemod_module

# And from now  on out you should be all set
lstuma
  • 31
  • 4
  • This raises a `TypeError: exec() globals must be a dict, not module`. If I'm not mistaken, you should pass `codemod_module.__dict__` to `exec()` – Emanuel P Mar 04 '23 at 19:51
-1

I can suggest you to first replace the name "codemod" and then apply exec:

exec(code.replace("codemod","cm"))

But it may rename other functions or variables with "codemod" in their name.

nicod
  • 16
  • 4
  • "codemod" is not found in the code string. It is just an arbitrary name I could use to save the string as a file and import it as a module. – holistone Mar 04 '23 at 20:14
  • 1
    This is not the same as `import ... as`. This is the same as `from ... import *`, in which case you might as well just use `exec(code)` – Emanuel P Mar 04 '23 at 20:31