2012-11-29 46 views
1

我正在開發一個PyQT應用程序。此應用程序能夠從數據庫加載一些數據,然後對這些數據進行各種分析。所有這些工作。但由於分析可能相當複雜,並且由於不會是唯一的用戶,我不得不開發一個帶有用戶定義腳本的系統。 基本上,有一個文本編輯器,用戶可以編寫自己的小型Python腳本(帶函數)。然後,用戶可以通過將文件作爲模塊(在應用程序內)加載來保存腳本或執行它。如何在整個應用程序中訪問變量/對象?

這裏有一個我的應用程序的簡化版本。

應用程序的核心是My_apps.py 和插件都在這裏同一個文件夾即Plugin_A.py

這是My_apps.py的代碼:

import sys,os 

class Analysis(object): 
    def __init__(self): 
     print "I'm the core of the application, I do some analysis etc..." 

    def Analyze_Stuff(self): 
     self.Amplitudes_1=[1,2,3,1,2,3] 
class Plugins(object): 

    def __init__(self): 
     newpath = "C:\Users\Antoine.Valera.NEUROSECRETION\Desktop\Model" #where the file is 
     sys.path.append(newpath) 

     Plugin_List=[] 
     for module in os.listdir(newpath): 
      if os.path.splitext(module)[1] == ".py": 
       module=module.replace(".py","") 
       Plugin_List.append(module) 

     for plugin in Plugin_List: 
      a=__import__(plugin) 
      setattr(self,plugin,a) 

    def Execute_a_Plugin(self): 
     Plugins.Plugin_A.External_Function(self) 


if __name__ == "__main__": 

    Analysis=Analysis() 
    Plugins=Plugins() 
    Plugins.Execute_a_Plugin() 

這裏是Plugin_A.py

def External_Function(self): 
    Analysis.Analyze_Stuff() 
    print Analysis.Amplitudes_1 

的代碼示例爲什麼會:

Traceback (most recent call last): 
    File "C:\Users\Antoine.Valera.NEUROSECRETION\Desktop\Model\My_Apps.py", line 46, in <module> 
    Plugins.Execute_a_Plugin() 
    File "C:\Users\Antoine.Valera.NEUROSECRETION\Desktop\Model\My_Apps.py", line 37, in Execute_a_Plugin 
    Plugins.Plugin_A.External_Function(self) 
    File "C:\Users\Antoine.Valera.NEUROSECRETION\Desktop\Model\Plugin_A.py", line 8, in External_Function 
    Analysis.Analyze_Stuff() 
NameError: global name 'Analysis' is not defined 

,但如果我添加了2線以下行,而不是Plugins.Execute_a_Plugin()

Analysis.Analyze_Stuff() 
print Analysis.Amplitudes_1 

那麼,它的工作原理。

我該如何向每個動態加載的插件指出他必須使用Analysis中已有的變量/對象?爲什麼我無法從插件中打印Analysis.Amplitudes_1?

謝謝!

回答

0

錯誤消息的頂部似乎非常清楚:名稱爲「分析」不導入的Plugin_A模塊的命名空間中,所以External_Function不能訪問它。

當您導入Plugin_A模塊時,它無法訪問導入模塊名稱空間My_apps中的名稱。所以它不能「看到」你在那裏創建的Analysis類的實例。

一個簡單的解決方案是改變External_Function(以及其它相關的功能)的簽名,以便它可以採取Analysis類的一個實例:

Plugin_A.py

def External_Function(self, analysis): 
    analysis.Analyze_Stuff() 
    print analysis.Amplitudes_1 

My_apps.py

... 

    def Execute_a_Plugin(self): 
     plugins.Plugin_A.External_Function(self, analysis) 

if __name__ == "__main__": 

    analysis = Analysis() 
    plugins = Plugins() 
    plugins.Execute_a_Plugin() 

請注意,我已更改了命名,以便實例名稱不會影響類名稱。

+0

好了,該解決方案運行良好!也許是最後一點。在我的申請中,有6個重要的課程。是否有一種簡單的方法可以自動將它們傳遞給插件函數,而無需單獨命名所有這些函數? (我可以將它們包含在* kargs或** kwargs中)。我嘗試了ARG = [Analysis,Class2,Class3,Class4,Class5,Class6],然後 'def Execute_a_Plugin(self):' 'plugins.Plugin_A.External_Function(self,Analysis,Class2,Class3,Class4,Class5,Class6 )' 我可以調用'plugins.Plugin_A.External_Function(self,* ARG)',它的工作
。但我更希望在函數定義中有* ARG。 – Vantoine

+0

@Vantoine。你可以有一個容器類,其所有其他類實例都是屬性,然後將容器傳遞給插件。 – ekhumoro

+0

這個怎麼樣? (它可以工作,但它可能不是最清潔的方式):在程序開始時,我在Class_List中添加Class_List = [Navigate,Requete,Analysis,Main,Infos,Mapping] : setattr __builtin __,Class .__ name __,Class)'然後,加載一個插件:'setattr(sys.modules [__ name __],plugin,__ import __(plugin))',插件是加載插件的名稱。 – Vantoine

0

你必須導入你的模塊。添加以下的Plugin_A.py

from My_apps import Analysis 

A = Analysis() 
A.Analyze_Stuff() 
print A.Amplitudes_1 
+0

如果我在Plugin_A中重新導入Analysis,它將在模塊啓動時覆蓋Analysis.Amplitudes_1的值。有沒有其他方法可以將Analysis變量鏈接到Plugin_A變量,而無需重新初始化所有核心模塊? – Vantoine

+0

我不確定,如果我瞭解你。 'Analysis'是一個類,所以你必須首先定義它的一個對象。比較我的編輯。這是你想要做的嗎? – Holger

+0

假設我啓動我的真實應用程序。就像這裏一樣,Analysis類是從一開始就啓動的。我得到我的數據,做我的stuf,使用位於Analysis類中的各種函數(如這裏的Analyze_stuff())分析它們,所有這些都在我的應用程序的核心中。我終於得到了一個振幅列表,這是Analysis的一個對象。這裏將是Analysis.Amplitudes_1。所有這些都是基本功能。現在,我想對這些數據執行一個非常具體的操作(Analysis.Amplitudes_1)。 – Vantoine

相關問題