首頁 >後端開發 >Python教學 >詳解使用Python中動態建立類別實例程式碼

詳解使用Python中動態建立類別實例程式碼

高洛峰
高洛峰原創
2017-03-26 10:07:531732瀏覽

在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中文網其他相關文章!

陳述:
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn