ОК, поэтому я пишу каркас, который ищет файлы python в подкаталогах с именем task.py
, а затем ищет классы, которые являются производными от базового класса Task
, и собирает их.
Я решил, что мне нужно добавить мета класс к Task
, но затем issubclass()
начал вести себя странным образом.
Вот как выглядит макет каталога:
start.py
tasks/__init__.py
tasks/base.py
tasks/sub/__init__.py # empty
tasks/sub/task.py
start.py:
#!/usr/bin/env python
from tasks.base import Task1, Task2
from tasks.sub.task import SubTask1, SubTask2
print "Normal import:"
print "is SubTask1 sub class of Task1? %s" % issubclass(SubTask1, Task1)
print "is SubTask2 sub class of Task2? %s" % issubclass(SubTask2, Task2)
from tasks import setup
print "Imp import:"
setup()
задачи / 1012 * INIT * .py
import os.path, imp, types
from tasks.base import Task1, Task2
# Find all task definitions
ALL_TASK1 = { }
ALL_TASK2 = { }
def _append_class(d, task, base):
if (type(task) == types.TypeType) and issubclass(task, base):
if task == base:
return
if not task.name in d:
d[task.name] = task
this_dir = os.path.dirname(os.path.abspath(__file__))
for root, dirs, files in os.walk(this_dir):
if not "task.py" in files:
continue
mod_name = "task"
f, pathname, description = imp.find_module(mod_name, [ root ])
m = imp.load_module(mod_name, f, pathname, description)
f.close()
for task in m.__dict__.itervalues():
_append_class(ALL_TASK1, task, Task1)
_append_class(ALL_TASK2, task, Task2)
def setup():
print "All Task1: %s" % ALL_TASK1
print "All Task2: %s" % ALL_TASK2
задачи / base.py
class MetaClass (type):
def __init__(cls, name, bases, attrs):
pass
class Base (object):
__metaclass__ = MetaClass
def method_using_metaclass_stuff(self):
pass
class Task1 (Base):
pass
class Task2 (object):
pass
задачи / суб / task.py
from tasks.base import Task1, Task2
class SubTask1 (Task1): # Derived from the __metaclass__ class
name = "subtask1"
class SubTask2 (Task2):
name = "subtask2"
Когда я запускаю setup.py
, я получаю следующий вывод (ALL_TASK1 dict пуст!):
Normal import:
is SubTask1 sub class of Task1? True
is SubTask2 sub class of Task2? True
Imp import:
All Task1: {}
All Task2: {'subtask2': <class 'task.SubTask2'>}
Но когда я закомментировал строку __metaclass__
в классе Base
(базовый класс Task1
), я получил ожидаемый вывод (текст ALL_TASK1 не пустой):
Normal import:
is SubTask1 sub class of Task1? True
is SubTask2 sub class of Task2? True
Imp import:
All Task1: {'subtask1': <class 'task.SubTask1'>}
All Task2: {'subtask2': <class 'task.SubTask2'>}
Я не понимаю, как мета-класс может влиять на issubclass()
, когда модуль импортируется с помощью функций imp
, но не когда модуль импортируется с обычным import
.
Может кто-нибудь объяснить мне (я использую python 2.6.1)?