This question already has answers here:
dynamically adding functions to a Python module
(2 answers)
Closed 2 years ago.
Suppose I create a module on the fly:
import imp
my_module = imp.new_module('my_module')
and I want to add n similar names/value to this module, something that would be equivalent to
my_module.a1 = None
my_module.a2 = None
my_module.a3 = None
...
How can I access a module namespace like a dictionary (or in a similar way) so that I can write something like
for i in range(n):
my_module.some_env_like_dict[f"a{i}"] = None
Also how can I remove these names in a similar way?
I understand that Python may not have a recommended or official way of doing this. Obviously this is not for any serious project.
I'm looking for a solution that is more elegant than using exec.
I think what you're doing is essentially correct, with just a few additions:
my_module = imp.new_module('my_module')
my_module.var1 = 123
This creates a module, and sets var1 to 123 within the module. You can access it as my_module.var1 just as you would for any other module.
To access the attributes from strings, you can do:
val = getattr(my_module, "var1")
setattr(my_module, "var1", val + 1)
This sets val to 123, then updates var1 in my_module with the value 124. You can also add new attributes to the module in this manner.
Related
In C++ I would write:
namespace LowerLevel{
int DoStuff() {}; //
}
And access it via:
LowerLevel::DoStuff()
How do I do both in Python?
The closest in spirit would be to use a module.
In a file lower_level.py you'd have
def do_stuff():
pass
and then elsewhere you'd do:
import lower_level
lower_level.do_stuff()
EDIT / addendums: That's the simple way. There's things like packages, where you'd have a folder lower_level, and inside that folder is an __init__.py identifying lower_level as a package. Inside that package you'd have .py files that'd be modules, or you put certain imports and declarations into the __init__.py. But it can also just remain empty. I guess packages would amount to nested namespaces.
- prog.py
\MyNameSpaceA
- __init__.py # just an empty file
- ObjA.py # A python Module
\SubPackageB
- __init__.py
- ObjB.py # another python module
One more option is to define everything in a function and return the locals. The advantage is that all definitions are in the same scope, so they can reference each other without any prefixes. Also you can have many of these in the same file.
import argparse
def InitLowerLevel():
def DoStuff():
return 1
def DoOtherStuff():
return DoStuff()
kFoo = 0
return argparse.Namespace(**locals())
lower_level = InitLowerLevel()
lower_level.DoStuff()
The argparse module may also be an option to consider, depending on your use case. The original answer is what I would say the better Software Development best practice, but this module provides the functionality you originally asked for.
It allows the dot notation to set and get variables. But complains less than dicts for when you are trying to add new variables/functions.
Python 3
>>> import argparse
>>> def my_test_function(): return
>>> ...
>>> args = argparse.Namespace()
Namespace()
>>> args.minutes = 5
>>> args.test = my_test_function
>>> args
Namespace(minutes=5, test=<function times_close_enough at 0x000001D2BEEAA550>)
Although the proper way to use argparse can be found at its documentation
, some further examples can be found on this StackOverflow question (helps if you understand better by example!)
This question already has answers here:
python - should I use static methods or top-level functions
(5 answers)
Closed 6 years ago.
I need something to organize some utilty functions.
Variant 1.
create module and write all functions in this module.
Variant 2.
(since python has no staticclass)
create class with only static methods in main module
In general, there is no big difference.Like :
var 1)
import functionsmodule
workers = functionmodule.get_all_workers(**kwargs)
var 2)
workers = FunctionClass.get_all_workers(**kwargs)
I like the second one though.
Questions is : what is best way to do such organization ?
You could also do:
from functionsmodule import get_all_workers, some_other_method
workers = get_all_workers(**kwargs)
After a couple of months learning python, this is my preferred solution. It cleans up the code without the need to reference a class or module. I'd only recommend this if your utilities method names WONT clash with builtins or other functions
I'd usually organise these re-usable/utilities within a common package and implement something like:
from common.functions import get_all_workers, some_other_method
workers = get_all_workers(**kwargs)
EDIT: Based on your "get_all_workers" method name - I'd imagine this should go into some sort of persistence/worker class rather than a general utilities class
This question already has answers here:
Parse a .py file, read the AST, modify it, then write back the modified source code
(13 answers)
Closed 8 years ago.
I am using the 'ast' module in python to create a Abstract Syntax Tree. I want to be able to edit the AST(I am editing with 'ast.NodeTransformer') and then take that new tree and write it to a new python file. According to the website "http://greentreesnakes.readthedocs.org/en/latest/index.html" there is no way to do this without using a third party package. Is this true, or can I write a AST to a new python file using the 'ast' module? If so, how do I do it? It seems like 'ast' would support this.
You will need a third party module called codegen.py, but it itself just uses the bulitin AST machinery under the hood its very simple. From there you can use the builtin ast.NodeTransformer machinery to transform the AST nodes.
import ast
import codegen
class Visitor(ast.NodeTransformer):
def visit_Num(self, node):
return ast.Num(42)
x = Visitor()
t = ast.parse('x + y + z + 3')
out = x.visit(t)
print codegen.to_source(out)
# x + y + z + 42
This question already has answers here:
How can I import a module dynamically given its name as string?
(10 answers)
Closed 9 years ago.
I'm doing
module = __import__("client.elements.gui.button", globals(), locals(), [], 0)
But it's only returning client.
What is my problem?
That's what __import__ does.
When the name variable is of the form package.module, normally, the top-level package (the name up till the first dot) is returned, not the module named by name.
You're not really supposed to use __import__; if you want to import a module dynamically, use importlib.import_module.
Accepted answer is correct, but if you read on in the docs you'll find that this can be gotten around with an admittedly unsettling "hack" by using __import__ like so:
module = __import__('client.elements.gui.button', fromlist=[''])
It doesn't really matter what you pass in for fromlist so long as it's a non-empty list. This signals to the default __import__ implementation that you want to do a from x.y.z import foo style import, and it will return the the module you're after.
As stated you should use importlib instead, but this is still a workaround if you need to support Python versions < 2.7.
It only obtains the top level, but you can also work around this like so:
module_name = 'some.module.import.class'
module = __import__(module_name)
for n in module_name.split('.')[1:]:
module = getattr(module, n)
# module is now equal to what would normally
# have been retrieved where you to properly import the file
This question already has answers here:
How can I import a module dynamically given its name as string?
(10 answers)
Closed 8 years ago.
Let me explain..
I want to do this:
a = "somedir.somefile"
b = "someclass"
from a import b
Well, I want to do this to import automatic all classes inside a directory, and I don't know how many classes are there.
a = "somedir.somefile"
b = "someclass"
module = __import__(a, globals(), locals(), [b], -1)
clazz = getattr(module, b)
now you can do this:
instance = clazz()
instance.method()
You need the __import__ built-in function. It's a bit fiddly to use, though, because it returns the top-level module, rather than the leaf of the path. Something like this should work:
from operator import attrgetter
module_path = 'a.b.c'
class_name = 'd'
module = __import__(module_path)
attribute_path = module_path.split('.') + [class_name]
# drop the top-level name
attribute_path = attribute_path[1:]
klass = attrgetter('.'.join(attribute_path))(module)
I think what you actually want to do is use __init__.py and __all__. Take a look at the modules tutorial for details.
Alternatively, there's exec. It will do what you're asking, but is probably not the best way to get there.