I have this code that carry module manually
exec("import" + moduleName + " as selectedModule")
importlib.reload(selectedModule)
But this code make
name 'seletedModule' is not defined
It is not happened on python2.x.
How to import this on python3?
If you need to import a library dynamically, don't use exec, its not safe.
Use importlib.import_module instead.
selected_module = importlib.import_module(module_name)
importlib.reload(selected_module)
As for the error you're getting: you're probably calling exec within a function scope, thus you'll need you manually set globals and locals to be the same in exec (Using a function defined in an exec'ed string in Python 3). Workaround:
exec("<do-stuff>", globals())
Related
Here's my code:
import numpy as np
import matplotlib.pyplot as plt
import astropy
import matplotlib
%matplotlib ipympl
import scatterplot_with_hist as sc
badx=[]
bady=[]
import badcomp as bc
#things like data5 and list2 are defined in here--I know that code is functional so I'll omit it for brevity
bc.getlist(start = 2000, end = 2200)
The module code is as follows:
def getlist(start, end):
for f in range(1):
for i in range(1238):
for n in range(int(start),int(end)):
if ((data[n]['col1'] - list2[i]) == 0):
badx.append(data[n]['col2'])
bady.append(data[n]['col3'])
If I run this code in the regular space (instead of importing it and running it as a function) it works fine. When I run it as an imported function, it won't recognize variables like data5, list2, and badx and bady.
Why?
Each Python module has it's own global namespace. That means that code in different modules that each try to access global variables will see separate ones. You can access another module's global variables by importing the module and interacting with the attributes of the module object.
In your code, the getlist function in the badcomp module is trying to interact with several global variables, including badx and bady for output, and data and list2 for input. It's not working because you've defined those in the interactive session, which uses the namespace of a module with the special name __main__.
While you could import __main__ from badcomp and interact with the global variables defined there via the module's attributes, that would be a really bad design, since it won't work if the module gets imported in any other way (e.g. by a different module you write later). Instead, the function should probably use variables defined in its own global namespace. The __main__ module is already importing badcomp (as bc), and can access things like badx and bady as bc.badx and bc.bady if the definitions are moved into the module.
Or you might reconsider if global variables are the best way for this function to work. It's often much better to use arguments and return values to pass data in and out of a function, rather than global variables. Maybe badx and bady should be defined within getlist and returned at the end. Meanwhile, data and list2 could be added as arguments to the function.
When a module is imported, it does NOT have access to the global or local namespace of the module that called it. You can get around this by creating a function that creates a variable in the global namespace inside the imported module and run the function from the calling module with each of the variables you need.
Example code (really bad design, but it'll teach you hopefully):
Put THIS in the imported module:
def putVarsInNamespace(variable, variableNameToInject)
exec("global %s" % variableName)
exec("%s = variable" % variableName)
Put THIS in the calling module:
test = 5
from <MODULENAME> import putVarsInNamespace
putVarsInNamespace(test, "test")
How this works: variableNameToInject is the name that you want the injected variable to be called. It then runs global variableNameToInject but it uses the VALUE of variableNameToInject which is the name that the injected variable should be called. This is useful when you want to inject multiple variables without using multiple functions. It then sets the variable name (the value of variableNameToInject) to the value of variable, and just like that it's injected.
In my Python code, I have :
from vmtk import vmtkscripts
The program has no issue finding "vmtkscripts.py".
However, in vmtkscripts.py I have "
__all__ = ['vmtkactivetubes']
for item in __all__:
exec('from '+item+' import *')
where "vmtkactivetubes.py" is in the same folder as "vmtkscripts.py".
After running I get "ModuleNotFoundError: No module named 'vmtkactivetubes'"
However, this "from vmtk import vmtkactivetubes" doesn't give me any error.
I would really appreciate if you could help me, why I get such a error?
This is a problem of scope,
try using:
exec('from '+item+' import *', globals())
This from the documentation:
In all cases, if the optional parts are omitted, the code is executed
in the current scope. If only globals is provided, it must be a
dictionary, which will be used for both the global and the local
variables. If globals and locals are given, they are used for the
global and local variables, respectively. If provided, locals can be
any mapping object. Remember that at module level, globals and locals
are the same dictionary. If exec gets two separate objects as globals
and locals, the code will be executed as if it were embedded in a
class definition.
I have a project in which I want to repeatedly change code in a class and then run other modules to test the changes (verification..). Currently, after each edit I have to reload the code, the testing modules which run it, and then run the test. I want to reduce this cycle to one line, moreover, I will later want to test different classes, so I want to be able to receive the name of the tested class as a parameter - meaning I need dynamic imports.
I wrote a function for clean imports of any module, it seems to work:
def build_module_clean(module_string,attr_strings):
module = import_module(module_string)
module = reload(module)
for f in attr_strings:
globals()[f]=getattr(module,f)
Now, in the name of cleanliness, I want to keep this function in a wrapper module (which will contain the one-liner I want to rebuild and test all the code each time), and run it from the various modules, i.e. among the import statements of my ModelChecker module I would place the line
from wrapper import build_module_clean
build_module_clean('test_class_module',['test_class_name'])
however, when I do this, it seems the test class is added to the globals in the wrapper module, but not in the ModelChecker module (attempting to access globals()['test_class_name'] in ModelChecker gives a key error). I have tried passing globals or globals() as further parameters to build_module_clean, but globals is a function (so the test module is still loaded to the wrapper globals), and passing and then using globals() gives the error
TypeError: 'builtin_function_or_method' object does not support item assignment
So I need some way to edit one module's globals() from another module.
Alternatively, (ideally?) I would like to import the test_class module in the wrapper, in a manner that would make it visible to all the modules that use it (e.g. ModelChecker). How can I do that?
Your function should look like:
def build_module_clean(globals, module_string, attr_strings):
module = import_module(module_string)
module = reload(module)
globals[module_string] = module
for f in attr_strings:
globals[f] = getattr(module, f)
and call it like so:
build_module_clean(globals(), 'test_class_module', ['test_class_name'])
Explanation:
Calling globals() in the function call (build_module_clean(globals()...) grabs the module's __dict__ while still in the correct module and passes that to your function.
The function is then able to (re)assign the names to the newly-loaded module and it's current attributes.
Note that I also (re)assigned the newly-loaded module itself to the globals (you may not want that part).
I'm trying to build a sort of script system in python that will allow small snippets of code to be selected and executed at runtime inside python.
Essentially I want to be able to load a small python file like
for i in Foo: #not in a function.
print i
Where somewhere else in the program I assign what Foo will be. As if Foo served as a function argument to the entire loaded python file instead of a single function
So somewhere else
FooToPass = GetAFoo ()
TempModule = __import__ ("TheSnippit",<Somehow put {'Foo' : FooToPass} in the locals>)
It is considered bad style to have code with side effects at module level. If you want your module to do something, put that code in a function, make Foo a parameter of this function and call it with the desired value.
Python's import mechanism does not allow to preinitialise a module namespace. If you want to do this anyway (which is, in my opinion, confusing and unnecessary), you have to fiddle around with details of the import mechanism. Example implementation (untested):
import imp
import sys
def my_import(module_name, globals):
if module_name in sys.modules:
return sys.modules[module_name]
module = imp.new_module(module_name)
vars(module).update(globals)
f, module.__file__, options = imp.find_module(module_name)
exec f.read() in vars(module)
f.close()
sys.modules[module_name] = module
return module
If I have a module Test and if I need to list all the functions in them, I do this:
import Test
dir(Test)
Unless I import the module I won't be able to use the functions defined in them.
But all the functions in __builtin__ module can be used without importing. But without import __builtin__ I am not able to do a dir(__builtin__). Does that mean we use the functions without importing the entire module?
from __builtin__ import zip
Is it something like the above? But if I do del zip, I get
NameError: name 'zip' is not defined
Can anyone please explain this behavior?
As explained in the Python language docs, names in Python are resolved by first looking them up in the local scope, then in any enclosing local scope, then in the module-level scope and finally in the namespace of the built-ins. So built-ins are somehow special-cased. They are not imported in your module's scope, but if a name is not found anywhere else, Python will look it up in the scope __builtin__.
Note that you can access the contents of this scope without importing it. A portable way to do this is
import sys
print(dir(sys.modules["__builtin__"]))
In CPython, this also works
print(dir(__builtins__))
but this is considered an implementation detail and might not be available for other Python implementations or future versions.
I'm by no means knowledgeable about python, but maybe dir(__builtins__), with an "s", is what you're after?
Works for me on plain Python 3.1.
when python interpreter start, it will by default execute something like
from __builtin__ import *
which allows you to use all the functions/attributes defined inside __builtin__ module
However to use __builtin__ symbol itself, you need to do
import __builtin__
this is how import statement syntax works.