2013-07-30 30 views
0

背景:我正在使用設備供應商提供的API模塊,它將設備登錄數據(設備主機名,會話ID等)存儲爲全局變量;我試圖弄清楚是否可以讓模塊的多個實例代表登錄到多個設備。全局模塊變量的多個實例?

到目前爲止,我已經嘗試了帶有測試代碼,沒有一個是有工作了幾個策略:

測試模塊代碼:statictest.py

count = 0 

class Test(): 
    @classmethod 
    def testcount(cls): 
    global count 
    count += 1 
    return count 

第一次嘗試:導入模塊多次和實例:

>>> import statictest as s1 
>>> import statictest as s2 
>>> s1.Test.testcount() 
1 
>>> s1.Test.testcount() 
2 
>>> s2.Test.testcount() 
3 

第二個嘗試:內部類導入模塊,實例化類:

#!/usr/bin/env python2.7 
class TestMod(): 
    s = __import__('statictest') 

    def test(self): 
    ts = self.s.Test() 
    return ts.testcount() 

t = TestMod() 
u = TestMod() 
print t.test() 
print u.test() 

那一個沒有工作之一:

[~/]$ ./moduletest.py 
1 
2 

這似乎是它應該是顯而易見的,但有什麼辦法來封裝模塊,使得多個實例可用?

+1

不需要。如果你想要多個實例,你應該使用一個類,而不是模塊級的值。通過將此狀態置於模塊級別,您的供應商表現得非常糟糕。 –

+0

請向供應商提交錯誤。這是由設計打破的。 – Keith

回答

1

下面似乎工作。它使用您的statictest.py模塊和一小部分,其他的答案思想的結合,創造出上下文管理器,這將使輕鬆切換,並使用任何模塊的不同實例:

from contextlib import contextmanager 
import importlib 
import random 
import sys 

MODULE_NAME = 'statictest' 
NUM_INSTANCES = 4 
instances = [] 

# initialize module instances 
for _ in xrange(NUM_INSTANCES): 
    if MODULE_NAME in sys.modules: 
     del sys.modules[MODULE_NAME] 

    module = importlib.import_module(MODULE_NAME) 
    for _ in xrange(random.randrange(10)): # call testcount a random # of times 
     module.Test.testcount() 

    instances.append(sys.modules[MODULE_NAME]) 

@contextmanager 
def statictest_inst(n): 
    save = sys.modules[MODULE_NAME] 
    sys.modules[MODULE_NAME] = instances[n] 
    yield instances[n] 
    sys.modules[MODULE_NAME] = save 

def get_counts(): 
    counts = [] 
    for i in xrange(NUM_INSTANCES): 
     with statictest_inst(i) as inst: 
      counts.append(inst.count) 
    return counts 

print 'initial counts', get_counts() 

choice = random.randrange(NUM_INSTANCES) 
print 'calling instance[{}].testcount()'.format(choice) 
with statictest_inst(choice) as inst: # use context manager 
    inst.Test.testcount() 

print 'counts after updating one of them', get_counts() 

輸出示例:

initial counts [2, 4, 4, 1] 
calling instance[2].testcount() 
counts after updating one of them [2, 4, 5, 1] 
1

我認爲這是不可能的,因爲Python模塊幾乎像單例一樣(實際上這是一個在Python中創建Singleton的有效方法)。例如,Refer to this SO threadthis one。此設計旨在防止同一模塊的多次導入,因爲它可能有點貴。 logging模塊就是一個很好的例子。您只需設置一次記錄器,並且由同一個解釋器運行的所有代碼以及導入logging的代碼都將寫入相同的日誌文件。

0

如果你把文件(statictest1.py,statictest2.py)的副本,將工作:

>>> import sttest1 as s1 
>>> import sttest2 as s2 
>>> s1.Test.testcount() 
1 
>>> s1.Test.testcount() 
2 
>>> s1.Test.testcount() 
3 
>>> s2.Test.testcount() 
1 
>>> s2.Test.testcount() 
2 
>>> s2.Test.testcount() 
+0

注意:如果第二個文件只是第一個文件的鏈接,則可以動態創建鏈接,然後導入「新」文件。有點奇怪,但似乎工作。 – Jiminion

0

如果模塊的狀態真的很好遏制,你可以寫一個上下文管理交換全球當你調用它時,會進入和退出模塊(即猴子補丁)。

例如:

import mymodule 

class ModuleState(object): 
    def __init__(self): 
     self.global_state = mymodule.global_state 

    def __enter__(self): 
     my_module.global_state = self.global_state 
     return self 

    def __exit__(self, type, value, traceback): 
     my_module.global_state = default_state 

default_state = mymodule.global_state 

# Init mymodule for state1 
state1 = ModuleState() 

# Init mymodule for state2 
state2 = ModuleState() 

# Init mymodule for state3 
state3 = ModuleState() 


# Do something in state2 
with state2: 
    mymodule.something() 
0

進口之間,你可以刪除sys.modules模塊,迫使它重新導入:

import sys 
import module 
del sys.modules['module'] 
import module as module2 
print(module is module2) # prints False