调度员python

时间:2009-04-15 12:22:09

标签: python

所有,我有以下“错误”的调度员:

def _load_methods(self):
    import os, sys, glob
    sys.path.insert(0, 'modules\commands')
    for c in glob.glob('modules\commands\Command*.py'):
        if os.path.isdir(c):
            continue
        c = os.path.splitext(c)[0]
        parts = c.split(os.path.sep )
        module, name = '.'.join( parts ), parts[-1:]
        module = __import__( module, globals(), locals(), name )
        _cmdClass = __import__(module).Command
        for method_name in list_public_methods(_cmdClass):
            self._methods[method_name] = getattr(_cmdClass(), method_name)
    sys.path.pop(0)

它会产生以下错误:

ImportError:没有名为commands.CommandAntitheft

的模块

其中Command * .py放在modules \ commands \ folder

有人可以帮助我吗?

一种可能的解决方案(它有效!!!)是:

    def _load_methods(self):
    import os, sys, glob, imp

    for file in glob.glob('modules/commands/Command*.py'):
        if os.path.isdir(file):
            continue
        module = os.path.splitext(file)[0].rsplit(os.sep, 1)[1]
        fd, filename, desc = imp.find_module(module,
                ['./modules/commands'])
        try:
            _cmdClass = imp.load_module( module, fd, filename, desc).Command
        finally:
            fd.close()

        for method_name in list_public_methods(_cmdClass):
            self._methods[method_name] = getattr(_cmdClass(), method_name)

仍然存在bobince(坦克:-))建议的所有风险,但现在我能够在“运行时”加载命令

2 个答案:

答案 0 :(得分:1)

  

sys.path.insert(0,'modules \ commands')

最好不要将相对路径放入sys.path。如果当前目录在执行期间发生变化,它将会中断。

此外,如果您从不同的目录运行到脚本,它将无法正常工作。如果您想使其相对于脚本的位置,请使用文件

为了安全起见,'\'字符也应转义为'\\',实际上它应该使用os.path.join()而不是依赖Windows路径规则。

sys.path.insert(0, os.path.abspath(os.path.join(__file__, 'modules')))
  

sys.path.pop(0)

危险。如果另一个导入的脚本使用了sys.path(可能),那么你将关闭错误的路径。同样重新加载自己的模块也会破坏。最好离开它的路径。

  

module,name ='。'。join(parts),parts [-1:]

请记住,您的路径包含细分“模块”。所以你有效地试图:

import modules.commands.CommandSomething

但是因为'modules.commands'已经在你添加的路径中搜索你真正想要的东西了:

import CommandSomething
  

__ import __(module,globals(),locals(),name)

'fromlist'也是一个列表,所以如果你真的想让它为你的局部变量写'CommandSomething',它应该是'[name]'。 (你几乎肯定不希望这样;把垃圾箱留空。)

  

_cmdClass = __import __(module).Command

是的,这不起作用,module是一个模块对象,__ import__想要一个模块名。你已经有了模块对象;为什么不只是“module.Command”?

我对这一切的反应很简单:太多魔法

你通过搞乱导入系统的内部结构,让自己变得过于困难并造成许多潜在问题和脆弱性。即使是经验丰富的Python程序员,这也很棘手。

使用显式导入的普通旧Python模块几乎肯定会更好。对命令列表进行硬编码实际上并不是很困难;将所有命令放在包中,__ init__.py说:

__all__= ['ThisCommand', 'ThatCommand', 'TheOtherCommand']

可能会重复一次文件名,但比魔法过多更简单,更强大。

答案 1 :(得分:1)

你真的需要将东西作为模块导入吗?如果您只是从文件系统中的任意位置加载代码,那么您可以使用execfile而不是摆弄模块路径等。

即。

for file in glob.glob('modules/commands/Command*.py'):
    if os.path.isdir(file):
        continue

    moddict={}
    execfile(file, moddict)
    _cmdClass = moddict['Command']
    ...