Finding and loading subclasses dynamically. issubclass(x, base_plugin.Plugin) fails.
Osmo Maatta
osmoma at gmail.com
Sun Aug 29 08:57:44 EDT 2010
Re-hi and thank you.
That solved my problem.
I can now see that the base_plugin.Plugin is loaded several times.
The numeric id(the_class) is not the same in all places.
Anyway, I thought that a class is always the same if it has been loaded
from the same module (in Linux/Unix; from the same file and inode). So
this experience was a bit confusing.
I need to learn more about how to set the search path (sys.path) right.
More Python!
Thanks
Osmo Antero
Grønland, Oslo
On 08/29/2010 01:06 PM, Peter Otten wrote:
> Osmo Maatta wrote:
>
>> Hello,
>>
>> Sub class test fails.
>> ======================
>> I have a program that needs to load plugin-classes during runtime.
>>
>> The program has these subdirectories (modules).
>>
>> $ tree
>> .
>> `-- test.py
>> |
>> |-- plugins
>> | |-- base_plugin.py
>> | |-- base_plugin.pyc
>> | |-- __init__.py
>> | `-- oca
>> | |-- __init__.py
>> | |-- open_clipart.py
>>
>>
>> The plugins (sub directory) contains one or more plugin modules, in this
>> test-case there is only one; oca/open_clipart.py.
>>
>> The plugins/base_plugin.py (contains class Plugin()) is a base class of
>> all plugins.
>>
>> I want to list and load all plugin-classes (that inherit from
>> base_plugin.Plugin). I have a Python code that successfully browses the
>> plugins, but the the test issubclass(x, base_plugin.Plugin) fails.
>>
>> Please see this Python code:
>> http://futuredesktop.com/tmp/test6.tar.gz
>>
>> Why the issubclass(entry, cls) test fails?
>
> base_plugin.py is imported twice, once as plugins.base_plugin and a second
> time as base_plugin. You can see that when you add a bit more debug code
> into your test.py:
>
>
> --- a/test.py Sun Aug 29 12:57:25 2010 +0200
> +++ b/test.py Sun Aug 29 12:58:25 2010 +0200
> @@ -24,6 +24,8 @@
> #print "entry's class<%s> -- cls's class=<%s>" %
> (obj1.get_name(), obj2.get_name(), )
>
> print "Check %s against %s" % (entry, cls, )
> + print entry.__bases__
> + print cls
>
> if issubclass(entry, cls):
> print "Found a subclass: " + key
>
> $ python test.py
> Importing plugins.base_plugin
> Importing plugins.oca.open_clipart
> Check <class 'plugins.oca.open_clipart.OpenClipArt'> against <class
> 'plugins.base_plugin.Plugin'>
> (<class 'base_plugin.Plugin'>,)
> <class 'plugins.base_plugin.Plugin'>
> Got subclasses= []
>
> The solution is to remove all sys.path gymnastics and to adapt your import
> statements accordingly:
>
> $ hg diff
> diff -r 9fe6129ba8fc plugins/oca/open_clipart.py
> --- a/plugins/oca/open_clipart.py Sun Aug 29 12:51:51 2010 +0200
> +++ b/plugins/oca/open_clipart.py Sun Aug 29 13:02:55 2010 +0200
> @@ -2,9 +2,7 @@
> import os
> import threading, thread
>
> -sys.path.insert(0, '..')
> -import base_plugin
> -#sys.path.insert(0, '../..')
> +from .. import base_plugin
>
> # ------------------------------------------
> # class OpenClipArt
> diff -r 9fe6129ba8fc test.py
> --- a/test.py Sun Aug 29 12:51:51 2010 +0200
> +++ b/test.py Sun Aug 29 13:02:55 2010 +0200
> @@ -1,7 +1,6 @@
> import os, sys
> import inspect
>
> -sys.path.insert(0, "plugins")
>
> # Thanks to http://www.luckydonkey.com/2008/01/02/python-style-plugins-
> made-easy/
> def find_subclasses(path, cls):
>
>
> $ python test.py
> Importing plugins.base_plugin
> Importing plugins.oca.open_clipart
> Check <class 'plugins.oca.open_clipart.OpenClipArt'> against <class
> 'plugins.base_plugin.Plugin'>
> Found a subclass: OpenClipArt
> Got subclasses= [<class 'plugins.oca.open_clipart.OpenClipArt'>]
>
> You should also remove the __init__.py from the folder containing test.py
> which is just begging for the same problem when you import your plugins as
> test.plugins.whatever.
>
> Peter
>
More information about the Python-list
mailing list