2012-11-02 21 views
5

ich folgende Projekthierarchie haben:Importieren von Bibliotheksklassen in Python

project_dir 
    lib 
    __init__.py 
    ... 
    some_script.py 
    ... 
    agent 
     __init__.py 
     ... 
     errors.py 
     some_agent_script.py 
     ... 

Es ist die SomeException Klassendefinition in lib/Mittel/erros.py ich folgenden Code verwenden sie innerhalb lib/Mittel/some_agent_script zu importieren. py:

from errors import SomeException 

auch Code, den ich verwende folgende in lib zu importieren/some_script.py

from agent.errors import SomeException 

Das Problem ist, wenn ich ein SomeException in lib/Mittel/some_agent_script.py dann lib/some_script.py anheben kann es nicht in einer außer Block fangen:

try: 
    # Here comes a call to lib/agent/some_agent_script.py function 
    # that raises SomeException 
except SomeException, exc: 
    # Never goes here 
    print(exc) 
except Exception, exc: 
    print(exc.__class__.__name__) # prints "SomeException" 

    # Let's print id's 
    print(id(exc.__class__)) 
    print(id(SomeException)) 
    # They are different! 

    # Let's print modules list 
    pprint.pprint(sys.modules) 

I in sys.modules sehen kann, das Modul erros zweimal importiert wurde: die erste mit ‚agent.errors‘ Schlüssel und der zweite ist mit ‚lib.agent.errors‘ Schlüssel

der folgende Code geht in Ordnung, aber es ist keine schöne Lösung:

agent_errors = sys.modules.get('agent.errors') 
from agent_errors import SomeException 

try: 
    # Here comes a call to lib/agent/some_agent_script.py function 
except SomeException: 
    print('OK') 

Was muss ich tun, damit dieses Modul nicht zweimal importiert wird?

+0

Was Python-Version ist es? –

+0

Es ist Python 2.6.6 – fey

+2

Verwandte lesen: [Frage SO] (http://stackoverflow.com/questions/1459236/module-relimported-if-imported-from-different-path), [PEP 395] (http://www.python.org/dev/peps/pep-0395/) –

Antwort

2

Sie sollten immer voll qualifizierte Importe verwenden.

from lib.agent.errors import SomeException 

Tun Sie dies in jedem Modul, das es verwendet. Dann wird es immer denselben Paketnamen haben. Sie sollten wahrscheinlich auch den Paketnamen der obersten Ebene ändern. Der Name "lib" ist zu allgemein.

Dies wird Ihnen auch ein paar Kopfschmerzen ersparen, wenn Sie zufällig ein Modul als Basis oder "Lager" -Modul bezeichnen. Angenommen, Sie haben ein Modul lib/agent/socket.py erstellt und in lib/agent/some_agent_script.py haben Sie import socket geschrieben. Sie würden nicht wirklich Ihr Modul bekommen, aber das Lager eins.

So ist es besser, sich angewöhnen, immer voll qualifizierte Paketnamen, aus einem gemeinsamen Stammnamen, wenn Sie können.

Eine Alternative sind absolute Importe.

from __future__ import absolute_import 

import .errors 

Beachten Sie den führenden Punkt. Dies importiert explizit aus dem aktuellen Paket. Es sollte auch dein Problem beheben, aber ich gebe zu, dass ich es nicht versucht habe.

+0

Klingt gut, aber Lib/Agent ist eine Bibliothek, die in mehreren Projekten verwendet wird. Es ist nicht gut, dort einen voll qualifizierten Namen anzugeben, weil der Agent in anderen Projekten nicht im lib-Modul gefunden werden kann. – fey

+0

@fey Ich habe meine Antwort mit einer alternativen Methode aktualisiert. – Keith

+0

Danke! Genau das habe ich gebraucht! Es gibt einen Zusatz: Es ist notwendig, absolute_import in beiden Modulen zu verwenden, die eine Ausnahme auslösen und behandeln. – fey