在Java中我們可以透過反射來根據類別名稱創建類別實例,那麼在Python我們怎麼實現類似功能呢?其實在Python有一個builtin函數import,我們可以使用這個函數來在運行時動態載入一些模組
簡介
在Java中我們可以透過反射來根據類別名稱創建類別實例,那麼在Python我們怎麼實現類似功能呢?
其實在Python有一個builtin函數import,我們可以使用這個函數來在運行時動態載入一些模組。如下:
def createInstance(module_name, class_name, *args, **kwargs): module_meta = __import__(module_name, globals(), locals(), [class_name]) class_meta = getattr(module_meta, class_name) obj = class_meta(*args, **kwargs) return obj
範例
首先我們建立一個目錄my_modules,其中包含三個檔案
* init.py: 模組文件
* my_module.py: 測試用的模組
* my_another_module: 另一個測試用的模組
my_module.py
from my_modules.my_another_module import * class MyObject(object): def test(self): print 'MyObject.test' MyObject1().test() MyObject2().test() MyAnotherObject().test() class MyObject1(object): def test(self): print 'MyObject1.test' class MyObject2(object): def test(self): print 'MyObject2.test'
my_another_module.py
class MyAnotherObject(object): def test(self): print 'MyAnotherObject.test'
test.py
def createInstance(module_name, class_name, *args, **kwargs): module_meta = __import__(module_name, globals(), locals(), [class_name]) class_meta = getattr(module_meta, class_name) obj = class_meta(*args, **kwargs) return obj obj = createInstance("my_modules.my_module", "MyObject") obj.test() MyObject.test MyObject1.test MyObject2.test MyAnotherObject.test
pyinstaller整合
對於使用pyinstaller打包的應用程序,如果使用上面的程式碼,則執行打包後的程式會出現下面的錯誤
Traceback (most recent call last): File "test.py", line 12, in <module> obj = createInstance("my_modules.my_module", "MyObject") File "test.py", line 7, in createInstance module_meta = __import__(module_name, globals(), locals(), [class_name]) ImportError: No module named my_modules.my_module Failed to execute script test
這裡錯誤的原因是pyinstaller 在打包分析類別的時候沒有分析到my_modules 下面的模組,所以執行報錯。
解決方案一:
在 test.py 中把 my_modules 下的模組手動 import,請看下面程式碼中的第一行。這種方法最簡單,但是顯然不太好。
import my_modules.my_module def createInstance(module_name, class_name, *args, **kwargs): module_meta = __import__(module_name, globals(), locals(), [class_name]) class_meta = getattr(module_meta, class_name) obj = class_meta(*args, **kwargs) return obj obj = createInstance("my_modules.my_module", "MyObject") obj.test()
解決方法二:
在使用pyinstaller 打包的時候,指定「–hidden- import”,如下
pyinstaller -D --hidden-import my_modules.my_module test.py
解決方法三:
動態修改python 運行時path,見下面程式碼中的前兩行,其中path我們可以透過環境變數或參數傳遞進來。顯然這種方法比前兩種方法靈活的多。
import sys sys.path.append(...) def createInstance(module_name, class_name, *args, **kwargs): module_meta = __import__(module_name, globals(), locals(), [class_name]) class_meta = getattr(module_meta, class_name) obj = class_meta(*args, **kwargs) return obj obj = createInstance("my_modules.my_module", "MyObject") obj.test()
以上是詳解使用Python中動態建立類別實例程式碼的詳細內容。更多資訊請關注PHP中文網其他相關文章!