I am having some trouble with dynamically importing Classes and attempting to run functions in said classes. This is my problem, specifically.
I have a python script dyn_imports.py in a director called dynamic_imports. Inside this folder is a subdir called scripts. In this scripts directory there is an __init__.py and a python class called AbhayScript.py. In the class AbhayScript, there is a function called say_hello()
My objective is: From dyn_imports.py, I would like to be able to import scripts.AbhayScript and call the function say_hello() in AbhayScript
So far, I have attempted a variety of options including __import__, importlib.import_module and pydoc.locate. All of these options give me access to the module AbhayScript but when I try a getattrs() or try to call the object, I get an error stating that its not callable or has no attribute.
dyn_imports.py - One of my experiments
myclass = 'scripts.AbhayScript'
import importlib
mymod = importlib.import_module(myclass)
mod,newclass = myclass.rsplit('.',1)
ncls = getattr(mod,newclass) #throws an AttributeError that 'str' object has no attribute
AbhayScript.py code
class AbhayScript(object):
def say_hello(self):
print 'Hello Abhay Bhargav'
The directory structure is as follows
The init.py in the scripts folder is empty.
I have attempted nearly all the solutions in Stackoverflow, but I am a little flummoxed by this one. What am I doing wrong?
I realize what I was doing wrong. I was importing the module and not referencing the class in the getattr function. I made the class declaration explicit in the __import__ function and in the getattr function and I was subsequently able to gain access to the functions in the class
Here's the code in dyn_imports.py
myclass = 'scripts.AbhayScript'
mod = __import__(myclass, fromlist = ['AbhayScript']) #class explicit
klass = getattr(mod, 'AbhayScript') #explicit class
klass().say_hello() #calls the function as desired
Related
I have a main function that dynamically imports a module in another file using importlib and then uses the dir built in method to look at attributes of that module. Is it bad to manually define the __dir()__ magic method in the module (file) itself?
main.py
import importlib
def main():
module = importlib.import_module("foo")
attributes = dir(module)
print(attributes)
foo.py
def __dir()__:
return [s]
s = "bar"
Is it looked down upon in the Python community to define dir at the module level as I have shown above?
As a newbie to python I finally managed to create my own customized logger in a class in an extra module (tools.py). One of the main achievements here is that I can set the name of the logger and with the name also the log file name.
I want to instantiate the logger in main in one module (recalc.py) and from here call a function prepData in another module (getData.py). That function prepData in module getData.py is supposed to use the logger instance I instantiated in recalc.py. prepData is calling other function in the same module that shall use the same logger instance.
I fail to get the grips on how do declare / instantiate the logger since only the in module recalc.py with the main function knows the correct name for the logger.
module tools.py
:
class Logg():
:
.
module recalc.py
import tools
from getData import prepData
:
lg = Logg("recalc", ...) # instantiate the logger
:
result = prepData(...)
.
module getData.py
:
def otherFunc()
lg.debug(...)
:
return X
def prepData(...)
lg.info(...)
:
x = otherFunc(...)
:
return RES
I read a lot about (not really existing) global variables in Python, also Python 3, one class used across multiple modules and others. The config.py solution implies to initiate the global variable in config.py itself. But that doesn't work for me as only the main module knows the logger name.
The workaround I have right now is not acceptable in the long run.
I appreciate any help.
I am trying to implement a small library for Python 3.5 but keep struggling with how to correctly handle the structuring of the packages/modules and how to get the imports to work.
I keep running into the problem where python complains of being unable to import some name with an error like
ImportError: cannot import name 'SubClass1'
This seems to happen when "SubClass1" needs to import some other module but that other module also needs to know about SubClass1 (a cyclic import).
I need the cyclic import in my library because the base class has a factory method that creates the proper subclass instances (there are also other situations where cyclic imports are needed, e.g. checking the type of a function argument needs the import of where that type is defined, but that module may itself need the class where that check is done: another cyclic dependency!)
Here is example code:
Root directory contains the subdirectory dir1. The directory dir1 contains and empty file init.py, a file baseclass.py and a file subclass1.py.
The file ./dir1/subclass1.py contains:
from . baseclass import BaseClass
class SubClass1(BaseClass):
pass
The file ./dir1/baseclass.py contains:
from . subclass1 import SubClass1
class BaseClass(object):
def make(self,somearg):
# .. some logic to decide which subclass to create
ret = SubClass1()
# .. which gets eventually returned by this factory method
return ret
The file ./test1.py contains:
from dir1.subclass1 import SubClass1
sc1 = SubClass1()
This results in the following error:
Traceback (most recent call last):
File "test1.py", line 1, in <module>
from dir1.subclass1 import SubClass1
File "/data/johann/tmp/python1/dir1/subclass1.py", line 1, in <module>
from . baseclass import BaseClass
File "/data/johann/tmp/python1/dir1/baseclass.py", line 1, in <module>
from . subclass1 import SubClass1
ImportError: cannot import name 'SubClass1'
What is the standard/best way to solve this problem, ideally in a way that is backwards compatible to python 2.x and python 3 up to version 3.2?
I have read elsewhere that importing the module instead of something from a module may help here but I do not know how to just import the module (e.g. subclass1) in a relative way because "import . subclass1" or similar does not work.
Your issue is caused by a circular import. The baseclass module is trying to import SubClass1 from the subclass1 module, but subclass is trying to import BaseClass right back. You get NameError because the classes haven't been defined yet when the import statements are running.
There are a few ways to solve the issue.
One option would be to change your style of import. Instead of importing the classes by name, just import the modules and look up the names as attributes later on.
from . import baseclass
class SubClass1(baseclass.BaseClass):
pass
And:
from . import subclass1
class BaseClass:
def make(self,somearg):
# ...
ret = subclass1.SubClass1()
Because SubClass1 needs to be able to use BaseClass immediately at definition time, this code may still fail if the baseclass module is imported before subclass1. So it's not ideal
Another option would be to change baseclass to do its import below the definition of BaseClass. This way the subclass module will be able to import the name when it needs to:
class BaseClass:
def make(self,somearg):
# .. some logic to decide which subclass to create
ret = SubClass1()
from .subclass1 import SubClass1
This is not ideal because the normal place to put imports is at the top of the file. Putting them elsewhere makes the code more confusing. You may want to put a comment up at the top of the file explaining why you're delaying the import if you go this route.
Another option may be to combine your two modules into a single file. Python doesn't require each class to have its own module like some other languages do. When you have tightly coupled classes (like the ones in your example), it makes a lot of sense to put them all in one place. This lets you avoid the whole issue, since you don't need any imports at all.
Finally, there are some more complicated solutions, like dependency injection. Rather than the base class needing to know about the subclasses, each subclass could register itself by calling some function and passing a reference to itself. For example:
# no imports of subclasses!
def BaseClass:
subclasses = []
def make(self, somearg):
for sub in self.subclasses:
if sub.accepts(somearg):
return sub()
raise ValueError("no subclass accepts value {!r}".format(somearg))
#classmethod
def register(cls, sub):
cls.subclasses.append(sub)
return sub # return the class so it can be used as a decorator!
And in subclass.py
from .baseclass import BaseClass
#BaseClass.register
class SubClass1(BaseClass):
#classmethod
def accepts(cls, somearg):
# put logic for picking this subclass here!
return True
This style of programming is a bit more complicated, but it can be nice since it's easier to extend than a version where BaseClass needs to know about all of the subclasses up front. There are a variety of ways you can implement this style of code, using a register function is just one of them. One nice thing about it is that it doesn't strictly require inheritance (so you could register a class that doesn't actually inherit from BaseClass if you wanted to). If you are only dealing with actual inheriting subclasses, you might want to consider using a metaclass that does all the registration of subclasses for you automatically.
I'm new to python. This is not my actual case, it's just my curiosity about importing nested class.
So I have a main.py and test.py.
test.py:
class one():
class two():
def twodef():
pass
so in my main.py, I can do 'import test' or 'from test import one'. But I got error when do: 'from test.one import two'.
error : ImportError: No module named one
Anyone can explain this?
You can only do from module import name for names that exist in the module's global scope - basically, names that are defined in top-level module code. Names that are defined in lower-level scopes - for example within classes as in your example - are not importable. You need to import the object that contains the name, and access it from there.
from test import one
my_two = one.two()
You could do the following:
from test import one
two_object = one.two()
two_object.twodef()
inside test.py
class One:
class Two:
#staticmethod
def twodef():
print("twodef")
My main logic:
from test import One
two_obj = One.Two
two_obj.twodef()
Remove the parenthesis at the end of class definition.
Coding standards:
Always declare your class names in upper camel case (class one => class One).
For more about scope
Preference:
And if you have a single class inside python file, always name that file in that class name but in lower camel case. (test.py => one.py). I have thought this as a standard earlier, but seems its practiced widely. I would use this because, if then project size grew and if you end up having a lot of classes and modules, it's logical and easy to access, rather than visiting the module to find the class name.
Ref1
Ref2
I am trying to create a new module and method as part of an existing library.
The existing library is called Bly.Pht. I create a new *.py file in this directory called Distance.py. In Distance.py I have the following:
class Distance:
def __init__(self, handle):
self.handle = handle
def test_func(t1, t2):
print "correctly executing"
From the Python shell, I do the following:
from Bly.Pht import Distance #this works fine
dist = Distance.test_func(input1, input2)
I get the error 'module' object has no attribute 'test_func'
Can anyone advise as to why this is happening?
Many thanks.
You are not importing the Distance class, you are importing the module that contains the Distance class. It can be fixed as:
dist = Distance.Distance.test_fund(input1, input2)
If you don't plan on including other functionality in Distance.py, it's probably a better idea to put the class definition in Bly/Pht/__init__.py or in Bly/Pht.py, in which case you could import it as you did. (Unlike other languages, Python doesn't encourage each class having its own file).
Python is not Java. If you created a file called Distance.py that defines a class called Distance, you need to from Bly.Pht.Distance import Distance. Or, if there's no good reason to make it a class, just write the method directly in the module.