2012-11-11 13 views
9

Dati due moduli, principali e x con il seguente contenuto:Condividi un singoletto attraverso moduli

principale:

class Singleton(object): 
    _instance = None 
    def __new__(cls, *args, **kwargs): 
     if not cls._instance: 
      cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) 
     cls._instance.x = 10 
     return cls._instance 
uvw = Singleton() 

if __name__ == "__main__": 
    print(id(uvw)) 
    uvw.x += 10 
    print(uvw.x) 
    import x 

e X, rispettivamente:

import main 

print(id(main.uvw)) 
print(main.uvw.x) 

vorrei ora aspettare che l'esecuzione principale restituirebbe gli stessi ID e il valore venti in entrambi i casi, ma ciò che ottengo è questo:

$ python main.py 
140592861777168 
20 
140592861207504 
10 

C'è un modo per garantire che lo uvw sia lo stesso oggetto in entrambi i posti?

+0

Si noti che l'intero punto del metodo '__new__' è di impedire all'utente di accedere a' main.uvw', poiché 'Singleton()' è garantito per restituire la stessa istanza ogni volta comunque. – Eric

+1

Quindi 'main' sta chiamando' x' che sta chiamando 'main' ...? Questa è una ricetta per la confusione/disastro. –

+0

possibile duplicato di [Importazione moduli: \ _ \ _ principale \ _ \ _ vs importazione come modulo] (http: // stackoverflow.it/questions/13181559/importing-modules-main-vs-import-as-module) –

risposta

6

Python carica ciascun modulo per nome una volta (a meno che non venga chiamato reload(module)). Se si esegue main.py, il modulo è __main__ (provare a stampare uvw.__class__.__module__). Quandoimporta main, il modulo chiamato main viene caricato per la prima volta.

Se definito uvw in un terzo modulo, o in x - fintanto che viene importato nello stesso modo in __main__ e x - sarebbe lo stesso oggetto.

5

Il problema è che la tua classe Singleton viene in qualche modo ricaricata e quindi perde il suo campo _instance nel secondo modulo.


Penso che questo funzionerà:

singleton.py:

class Singleton(object): 
    _instance = None 
    def __new__(cls, *args, **kwargs): 
     if not cls._instance: 
      cls._instance = super(Singleton, cls).__new__(cls, *args, **kwargs) 
     cls._instance.x = 10 
     return cls._instance 

a.py:

from singleton import Singleton 
uvw = Singleton() 
print(id(uvw)) 
uvw.x += 10 
print(uvw.x) 

b.py:

from singleton import Singleton 
uvw = Singleton() 
print(id(uvw)) 
uvw.x += 10 
print(uvw.x) 

main.py

import a 
import b 
+0

Non voglio dividere ulteriormente il mio programma ... sarebbe un po 'l'ultima risorsa per me :) – dom0

+0

Se il codice deve importare il modulo principale da un altro file, sta succedendo qualcosa di sospetto. – Eric

+0

Vedere il dupe, @Eric; 'sys.modules ['__ main __']' * è * diverso da 'sys.modules ['x']'. –

1

ho scoperto che il problema è che main viene caricato due volte quando è eseguito dalla riga di comando, una volta come __main__ e la seconda volta importati da x come main.

ho trovato un hack molto male per aggirare il secondo carico:

sys.modules["main"] = sys.modules["__main__"] 

Separare il modulo principale e la classe Singleton non è favorevole nel mio caso.

+3

Per evitare il trucco malvagio, potresti definire 'uvw' in un modulo che non è eseguito come uno script e quindi semplicemente importare quel modulo nel tuo script principale – jfs

Problemi correlati