I'm trying to instantiate a class in a submodule using a string name. I've been trying to follow this SO question unsuccessfully:
Python dynamic instantiation from string name of a class in dynamically imported module
I've created the following directory structure:
__init__.py
mymodule/
├── __init__.py
└── MyClass.py
MyClass.py contains:
class MyClass():
def __init__(self, someparam):
print(someparam)
From python I try the following which produces an error.
getattr(importlib.import_module('mymodule'), 'MyClass')
AttributeError: 'module' object has no attribute 'MyClass'
I've tried most of the other solutions put forth in the referenced question and not gotten any of them to work with this setup.
Here other failed attempts based on answers I've tried to follow to illustrate what I've tried and failed at:
import importlib
module = importlib.import_module('mymodule')
class_ = getattr(module, 'MyClass')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
AttributeError: 'module' object has no attribute 'MyClass'
Your code is equivalent to:
from mymodule import MyClass
mymodule doesn't contain MyClass, so you will get an error. You want the equivalent of:
from mymodule.myclass import MyClass
That would be:
getattr(importlib.import_module('mymodule.MyClass'), 'MyClass')
Related
I had create a Python package in my project with name text_analysis, and inside a class TextAnalysis with a method search_records
When I write a test in the main.py I can import TextAnalysis, but the ojbect (with IDE) doesn't show the method search_records. If I write the test.search_records(barcode) I got this error message:
Traceback (most recent call last):
File "C:..../main.py", line 19, in <module>
analysys = TextAnalysis(bib)
TypeError: 'module' object is not callable
Make sure that you are defining a class in TextAnalysis.py that contains the modules you want to call. If you would rather call individual modules without a class structure within TextAnalysis.py, call them as TextAnalysis.module_name().
Here is a simple example: Class vs Module structure
I'm writing a Python package that looks like this:
|- datum/
|- __init__.py
|- database.py
__init__.py
from .database import Database
def connect(url):
print(Database) # for debugging
return Database(url)
database.py
class Database(object):
def __init__(self, url):
self.url = url
...more methods
This is installed as a package called datum in development mode. If I call connect outside of this package like:
import datum
db = datum.connect('postgresql://xxx')
...this is the output:
<class 'datum.database.Database'>
Traceback (most recent call last):
File "Z:\AIS\Flask\ais\engine\scripts\load_pwd_parcels.py", line 30, in <module>
source_db = Database(source_db_url)
NameError: name 'Database' is not defined
I'm confused because the class is being imported fine -- I can print it and even run dir on it and see all my methods -- but when I try to instantiate something it's "not defined". Does anyone know what I'm doing wrong here?
A NameError means that a local or global name cannot be found. I would make sure that your "load_pwd_parcels.py" file includes:
from database import Database
Alternatively, you could do:
import database
source_db = database.Database(source_db_url)
The latter option is a great choice because it gives database its very own namespace. In the words of Tim Peters in PEP 20 -- The Zen of Python:
"Namespaces are one honking great idea - let's do more of those!"
I have a script that does the following:
import imp
imp.load_source("storage_configuration_reader","/bi/opt/RNAspace/rnaspace_sources/rnaspace/rnaspace/rnaspace/dao/storage_configuration_reader.py")
Later on, I call a class of the this module with the same name:
config = storage_configuration_reader()
If I import it like the above I get the following NameError NameError: global name 'storage_configuration_reader' is not defined but if I use the following code:
import imp
imp.load_source("storage_configuration_reader","/bi/opt/RNAspace/rnaspace_sources/rnaspace/rnaspace/rnaspace/dao/storage_configuration_reader.py")
import storage_configuration_reader
config = storage_configuration_reader()
Then I get this error TypeError: 'module' object is not callable
Changing the name of the imp.load_source doesn't help to import the object:
import imp
imp.load_source("storage_configuration","/bi/opt/RNAspace/rnaspace_sources/rnaspace/rnaspace/rnaspace/dao/storage_configuration_reader.py")
<module 'storage_configuration' from '/bi/opt/RNAspace/rnaspace_sources/rnaspace/rnaspace/rnaspace/dao/storage_configuration_reader.pyc'>
import storage_configuration
config = storage_configuration_reader()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
NameError: name 'storage_configuration_reader' is not defined
Which is the best way (AKA working way) to import an object like this?
Info: The storage_configuration_reader definition:
class storage_configuration_reader(object):
"""
Class configuration_reader: this object read the config file and return the
different configuration values
"""
...
imp.load_source loads the module using the given path and name it using the new name, it's not like from your_module_at_path import your_class_by_name, it's just like import your_module_at_path as new_name (not exactly the same).
Besides, you need to assign the name to a variable to use it:
wtf=imp.load_source("new_module_name", your_path)
#wtf is the name you could use directly:
config = wtf.storage_configuration_reader()
the name new_module_name is stored as a key in dictionary sys.modules, you can use it like this:
sys.modules['new_module_name'].storage_configuration_reader()
A simpler way to import a module from some other directory is adding the module's path to sys.path:
import sys
sys.path.append("/bi/opt/RNAspace/rnaspace_sources/rnaspace/rnaspace/rnaspace/dao")
import storage_configuration_reader
config = storage_configuration_reader.storage_configuration_reader()
I create two files: test.py and test1234.py
test.py contains:
import test1234
t = test1234.test()
test1234.py contains:
class test():
def __init__(self):
When put in the same directory, python test.py runs without error.
However, if I create a directory test1234 and put test1234.py and a blank init.py in this directory, python test.py gives the error:
AttributeError: 'module' object has no attribute 'test'
What do I need to do for test.py to be able to see the test class in test1234.py?
You have to import it through the package, or put it in __init__.py.
import test1234.test1234
t = test1234.test1234.test()
I'm new to unittesting in python. I tried the unittest example from the documentation:
import random
import unittest
class TestSequenceFunctions(unittest.TestCase):
def setUp(self):
self.seq = list(range(10))
def test_shuffle(self):
# make sure the shuffled sequence does not lose any elements
random.shuffle(self.seq)
self.seq.sort()
self.assertEqual(self.seq, list(range(10)))
# should raise an exception for an immutable sequence
self.assertRaises(TypeError, random.shuffle, (1,2,3))
def test_choice(self):
element = random.choice(self.seq)
self.assertTrue(element in self.seq)
def test_sample(self):
with self.assertRaises(ValueError):
random.sample(self.seq, 20)
for element in random.sample(self.seq, 5):
self.assertTrue(element in self.seq)
if __name__ == '__main__':
unittest.main()
Running this code gives me following error on the commandline:
D:\src>python foo.py
Traceback (most recent call last):
File "foo.py", line 8, in <module>
class TestSequenceFunctions(unittest.TestCase):
AttributeError: 'module' object has no attribute 'TestCase'
I'm using ActiveState Python 3.2. Why do I get an attribute error here?
Most likely you have a second unittest module or package in your python path.
If you created a unittest.py file or a unittest directory containing an __init__.py file, python could find that before it finds the normal module in the standard python library.
Naming a local module or package unittest is the equivalent of naming a local variable list or dict or map; you are masking the built-in name with a local redefinition.
Rename that module or package to something else to fix this.