我在一個目錄中有一堆Python模塊,都是派生類。我需要一個「runner」腳本,爲每個模塊實例化其中的類(實際的類名可以通過模塊文件名構建),並在每個模塊上調用「go」方法。在Python中創建「runner」腳本的最佳方式是什麼?
我不知道有多少模塊是有的,但我可以列出所有的人都通過的東西通配符的目錄,如「機器人_ *。PY」
我認爲這是一些有關「元編程」,但怎麼可能是最好的(最優雅的)方法呢?
我在一個目錄中有一堆Python模塊,都是派生類。我需要一個「runner」腳本,爲每個模塊實例化其中的類(實際的類名可以通過模塊文件名構建),並在每個模塊上調用「go」方法。在Python中創建「runner」腳本的最佳方式是什麼?
我不知道有多少模塊是有的,但我可以列出所有的人都通過的東西通配符的目錄,如「機器人_ *。PY」
我認爲這是一些有關「元編程」,但怎麼可能是最好的(最優雅的)方法呢?
def run_all(path):
import glob, os
print "Exploring %s" % path
for filename in glob.glob(path + "/*.py"):
# modulename = "bot_paperino"
modulename = os.path.splitext(os.path.split(filename)[-1])[0]
# classname = "Paperino"
classname = modulename.split("bot_")[-1].capitalize()
# package = "path.bot_paperino"
package = filename.replace("\\", "/").replace("/", ".")[:-3]
mod = __import__(package)
if classname in mod.__dict__[modulename].__dict__.keys():
obj = mod.__dict__[modulename].__dict__[classname]()
if hasattr(obj, "go"):
obj.go()
if __name__ == "__main__":
import sys
# Run on each directory passed on command line
for path in sys.argv[1:]:
run_all(sys.argv[1])
需要在每個路徑的__init__.py
要「跑」。 根據您的意願更改「bot_」。 在windows和linux上運行。
你可以使用__import__()
加載每個模塊,使用dir()
找到每個模塊中的所有對象,發現這是類的所有對象,實例化它們,並運行go()
方法:
import types
for module_name in list_of_modules_to_load:
module = __import__(module_name)
for name in dir(module):
object = module.__dict__[name]
if type(object) == types.ClassType:
object().go()
這裏有一種方法要做到這一點從我的頭頂,我必須假設你的模塊的結構位:
mainDir/ runner.py package/ __init__.py bot_moduleA.py bot_moduleB.py bot_moduleC.py
在亞軍你會發現這一點:
import types
import package
for moduleName in dir(package):
module = package.__dict__[moduleName]
if type(module) != types.ModuleType:
continue
for klassName in dir(module):
klass = module.__dict__[klassName]
if type(klass) != types.ClassType:
continue
klass().go()
我會嘗試:
import glob
import os
filelist = glob.glob('bot_*.py')
for f in filelist:
context = {}
exec(open(f).read(), context)
klassname = os.path.basename(f)[:-3]
klass = context[klassname]
klass().go()
這隻會辦班同樣命名的模塊,我認爲這是你想要的。它也沒有要求頂級目錄成爲一個包。
要注意,glob返回完整的路徑,包括前面的目錄,因此使用os.path.basename(f)[: - 3]來獲取類名。
或`os.path.splitext(os.path.basename(f))[0]`(你永遠不知道未來對擴展名有什麼影響:) – tzot 2010-05-16 21:45:52
使用您使用的類型模塊和__dict__來修改我的答案。這使得更清潔和動態的方法。 – pboucher 2009-01-23 18:58:45