2009-04-15 111 views
0

HY一切,我有以下的 「錯誤」 的調度員:調度蟒蛇

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) 

它產生以下錯誤:

導入錯誤:沒有模塊名爲commands.CommandAntitheft

where命令*。 py被放入modules \ commands \文件夾中

有人可以幫助我嗎?

一個可能的解決方案(它的工作原理!!!)是:

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建議(坦克:-))的所有風險,但現在我能夠在「運行」加載命令

+0

嗨@ DrFalk3n我偶然發現了你的舊問題。時代已經發生了變化,這個問題並沒有真正符合當前有關什麼樣的問題的指導方針。你想讓它保持這種方式還是自己編輯它,或者我可以繼續編輯它? – Breeze 2016-07-07 11:10:50

+0

請隨時改變它,thkk – DrFalk3n 2016-07-08 15:00:02

回答

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]'。 (你幾乎肯定不希望這樣,離開fromlist裏是空的。)

_cmdClass = __import__(module).Command

是啊,這是行不通的,模塊是一個模塊對象,__import__想要一個模塊名稱。你已經有了模塊對象;爲什麼不只是「module.Command」?

我對這一切的反應很簡單:魔法太多

你讓自己過於困難,並通過混淆導入系統的內部來創造很多潛在的問題和脆弱性。即使對於有經驗的Python程序員來說,這也是棘手的問題。

你肯定會更好地使用明確導入的普通舊Python模塊。對命令列表進行硬編碼確實不是很大的困難;讓你的所有命令的封裝,__init__.py說:

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

可重複一次的文件名,但比一個神奇的過量更簡單,更可靠。

1

你真的需要導入東西作爲模塊嗎?如果您只是從文件系統中的任意位置加載代碼,那麼您可以使用execfile而不是模塊路徑等。

即。

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

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