I want to implement a plugin based file uploader which can upload files to different services. It loads all the python modules from a directory and then calls them based on the service to upload to.
I have a simple BaseHandler which is just an abstract base class for all plugins
import abc
class BaseHandler():
__metaclass__ = abc.ABCMeta
#abc.abstractmethod
def start(self,startString):
return
I have a simple plugin which inherits from BaseHandler
from BaseHandler import BaseHandler
class Cloud(BaseHandler):
def start(self,startString):
return
And the actual code which loads plugins and calls them
import logging
import os
import sys
from BaseHandler import BaseHandler
all_plugins = {}
def load_plugins():
plugin_dir = os.path.join(os.path.dirname(os.path.realpath(__file__)),"Handlers")
plugin_files = [x[:-3] for x in os.listdir(plugin_dir) if x.endswith(".py")]
sys.path.insert(0,plugin_dir)
for plugin in plugin_files:
mod = __import__(plugin)
logging.info('Plugins have been loaded from the directory '+plugin_dir)
for plugin in BaseHandler.__subclasses__():
logging.info('Plugin:'+plugin.__name__)
return BaseHandler.__subclasses__()
logging.basicConfig(level=logging.DEBUG)
loadedPlugins = load_plugins()
for plugin in loadedPlugins:
all_plugins[plugin.__name__]= plugin.__class__
handle = all_plugins[plugin.__name__]()
When I try to create the actual object of the plugin in the last line of the script
handle = all_plugins[plugin.__name__]()
I get an error TypeError: __new__() takes exactly 4 arguments (1 given).
Edit: added full trace back
Traceback (most recent call last):
File "C:\TestCopy\Test.py", line 24, in <
module>
handle = all_plugins[plugin.__name__]()
TypeError: __new__() takes exactly 4 arguments (1 given)
You are registering the meta class, not the plugin itself;
>>> BaseHandler()
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: Can't instantiate abstract class BaseHandler with abstract methods start
I think you meant to store the plugin itself:
all_plugins[plugin.__name__] = plugin
The __class__ attribute is the BaseHandler class instead; plugin objects are classes, not instances.
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 want to monkey patch a method of a library class to define a different default for a param. This fails:
from functools import partial
class A(object):
def meth(self, foo=1):
print(foo)
A.meth = partial(A.meth, foo=2)
a = A()
a.meth()
with:
Traceback (most recent call last):
File "...", line 10, in <module>
a.meth()
TypeError: meth() missing 1 required positional argument: 'self'
what is the correct way of doing this?
(Original code is using getattr on the method names in a loop)
The answers in the question linked involve defining a new module-level function - I would like to avoid a new function definition
Use partialmethod:
In [32]: from functools import partialmethod
In [33]: A.meth = partialmethod(A.meth, foo=2)
In [34]: a = A()
In [35]: a.meth()
2
I have been learning working with classes in python after learning OOPs in c++.
I am working on a project, where I have a class defined in one file, and an important function to be used in the class in the seperate file.
I have to call the class in the first file, but I am getting the ImportError.
Great, if you could help.
try1.py
from try2 import prnt
class a:
def __init__(self):
print("started")
def func1(self):
print("func1")
prnt()
try2.py
from try1 import a
b = a()
b.func1()
def prnt():
b.func()
As for eg, in the above example, when I am running try1.py, I am getting an ImportError: cannot import name 'prnt'.
You absolutely need to redesign your project. Even if you did manage to get away with the cyclic imports (ie by moving the import to inside the function - but don't do it) you will still get a NameError: name 'b' is not defined since b is not define in prnt.
Unless prnt can't be defined in class a (why?), consider defining prnt in a third, "utils" file and import it in both try1.py and try2.py and pass an object to it so it can access all of its attributes.
Just run your code, read the error, and deduct something from it.
When you run it, here is the error message :
Traceback (most recent call last):
File "C:\Users\Kilian\Desktop\Code\Garbage\tmp.py", line 7, in <module>
from temp2 import prnt
File "C:\Users\Kilian\Desktop\Code\Garbage\temp2.py", line 1, in <module>
from tmp import a
File "C:\Users\Kilian\Desktop\Code\Garbage\tmp.py", line 7, in <module>
from temp2 import prnt
ImportError: cannot import name prnt
Your script is trying to import something it already has tried to import earlier on. Python is probably deducing that it can't import it. :)
I have two different files, containing two different classes (Let's call them Foo and Bar).
In the file (Foo.py) with class Foo, I have:
class Foo:
def __init__(self):
...
And in the file (Bar.py) with class Bar, I have:
from Foo import Foo
class Bar(Foo.Foo):
def __init__(self):
...
When I run my code, I get this TypeError:
Traceback (most recent call last):
File "Bar.py", line 2, in <module>
class Bar(Foo.Foo):
TypeError: Error when calling the metaclass bases
__init__() takes exactly 1 argument (4 given)
Why is it telling me I have 4 arguments to pass __init__ when the only argument I have in the code is self?
It looks to me like your problem is that you are importing the class directly, but then trying to access it via the module name.
If you have a class Foo inside a module source file foo.py then you can use it like this:
import foo
new_instance = foo.Foo()
You can also do this:
from foo import Foo
new_instance = Foo()
But you are trying to do this:
from Foo import Foo
new_instance = Foo.Foo()
In the expression Foo.Foo(), the first Foo is your class. Then after the . Python parses out Foo and looks for a class member called Foo.
Note: I suggest you comply with PEP 8 guidelines, and your modules should use lower-case names. Thus foo.py rather than Foo.py.
http://legacy.python.org/dev/peps/pep-0008/
I've got a class that I'm trying to write called dbObject and I'm trying to import it from a script in a different folder. My structure is as follows:
/var/www/html/py/testobj.py
/var/www/html/py/obj/dbObject.py
/var/www/html/py/obj/__init__.py
Now, __init__.py is an empty file. Here are the contents of dbObject.py:
class dbObject:
def __init__():
print "Constructor?"
def test():
print "Testing"
And here's the contents of testobj.py:
#!/usr/bin/python
import sys
sys.path.append("/var/www/html/py")
import obj.dbObject
db = dbObject()
When I run this, I get:
Traceback (most recent call last):
File "testobj.py", line 7, in <module>
db = dbObject()
NameError: name 'dbObject' is not defined
I'm new to Python, so I'm very confused as to what I'm doing wrong. Could someone please point me in the right direction?
EDIT: Thanks to Martijn Pieters' answer I modified my testobj.py as follows:
#!/usr/bin/python
import sys
sys.path.append("/var/www/html/py")
sys.path.append("/var/www/html/py/dev")
from obj.dbObject import dbObject
db = dbObject()
However, now when I run it I get this error:
Traceback (most recent call last):
File "testobj.py", line 7, in <module>
db = dbObject()
TypeError: __init__() takes no arguments (1 given)
Is this referring to my init.py or the constructor within dbObject?
EDIT(2): Solved that one myself, the constructor must be able to take at least one parameter - a reference to itself. Simple fix. Looks like this problem is solved!
EDIT (Final): This is nice - I can cut out the import sys and sys.path.append lines and it still works in this instance. Lovely.
You need to import the class from the module:
from obj.dbObject import dbObject
This adds the class dbObject directly to your local namespace.
Your statement import obj.dbObject adds the name obj to the local namespace, so you could also do this instead:
db = obj.dbObject.dbObject()
because obj.dbObject is the dbObject.py module in your obj package directory.