2009-08-11 12 views
274

Ich habe eine Datei mit der Bezeichnung tester.py, unter /project.Importieren Sie eine Datei aus einem Unterverzeichnis?

/project hat ein Unterverzeichnis lib, mit einer Datei BoxTime.py genannt genannt:

/project/tester.py 
/project/lib/BoxTime.py 

Ich möchte BoxTime von tester importieren. Ich habe dies versucht:

import lib.BoxTime 

Welche Folge:

Traceback (most recent call last): 
    File "./tester.py", line 3, in <module> 
    import lib.BoxTime 
ImportError: No module named lib.BoxTime 

Irgendwelche Ideen, wie BoxTime aus dem Unterverzeichnis zu importieren?

EDIT

Die __init__.py war das Problem, aber vergessen Sie nicht, BoxTime als lib.BoxTime oder Verwendung zu beziehen:

import lib.BoxTime as BT 
... 
BT.bt_function() 

Antwort

353

Werfen Sie einen Blick auf die Pakete Dokumentation (Abschnitt 6.4) hier: http://docs.python.org/tutorial/modules.html

Kurz gesagt, müssen Sie eine leere Datei mit dem Namen

__init__.py 

im Verzeichnis "lib".

+28

Warum fühlt sich es * Hacky *? So markiert Python sichere/verfügbare Importverzeichnisse. – IAbstract

+5

Es markiert nicht nur sichere/verfügbare Importverzeichnisse, sondern bietet auch die Möglichkeit, beim Import eines Verzeichnisnamens einen Initialisierungscode auszuführen. – Sadjad

+12

Ja, das ist hacky und sogar dreckig, und meiner Meinung nach sollte die Sprache nicht die Möglichkeit bieten, Dateien über das Dateisystem zu laden. In PHP haben wir das Problem gelöst, indem wir den Userland-Code mehrere Autoloading-Funktionen registrieren lassen, die aufgerufen werden, wenn ein Namespace/Klasse fehlt. Dann hat die Community den PSR-4-Standard produziert und Composer implementiert es, und heutzutage muss sich niemand darum kümmern. Und keine doofen hartcodierten '__init__'-Dateien (aber wenn du es willst, registrier einfach einen Autoloading-Haken! Das ist der Unterschied zwischen _hacky_ und _hackable_). –

11

Versuchen Sie import .lib.BoxTime. Weitere Informationen zum relativen Import finden Sie unter PEP 328.

+2

Ich glaube nicht, dass ich jemals diese Syntax zuvor gesehen habe. Gibt es einen starken Grund (nicht) diese Methode zu verwenden? – tgray

+1

Warum war das nicht die Antwort? Sicher, wenn Sie die ganze Sache machen wollen, sollten Sie das tun. Aber das war nicht die ursprüngliche Frage. –

+0

Das gibt mir: ValueError: Versuchter relativer Import in Nicht-Paket – Alex

19

Enthält Ihr lib-Verzeichnis eine __init__.py Datei?

Python verwendet __init__.py um festzustellen, ob ein Verzeichnis ein Modul ist.

108
  • Erstellen Sie ein Unterverzeichnis namens lib. Erstellen Sie eine leere Datei mit dem Namen lib\__init__.py.
  • In lib\BoxTime.py, schreiben Sie eine Funktion foo() wie folgt aus:

    def foo(): 
        print "foo!" 
    
  • In Ihrem Client-Code in das Verzeichnis über lib, schreiben:

    from lib import BoxTime 
    BoxTime.foo() 
    
  • Führen Sie Ihre Kundennummer ein.Sie erhalten:

    foo! 
    

Viel später - unter Linux, würde es so aussehen:

% cd ~/tmp 
% mkdir lib 
% touch lib/__init__.py 
% cat > lib/BoxTime.py << EOF 
heredoc> def foo(): 
heredoc>  print "foo!" 
heredoc> EOF 
% tree lib 
lib 
├── BoxTime.py 
└── __init__.py 

0 directories, 2 files 
% python 
Python 2.7.6 (default, Mar 22 2014, 22:59:56) 
[GCC 4.8.2] on linux2 
Type "help", "copyright", "credits" or "license" for more information. 
>>> from lib import BoxTime 
>>> BoxTime.foo() 
foo! 
+0

Können Sie einen Link zur Python-Dokumentation bereitstellen, wo dies erklärt wird? Vielen Dank! – Zenon

+1

@Zenon, versuchen Sie Folgendes: docs.python.org/tutorial/modules.html#packages – hughdbrown

32

Sie können versuchen, es in sys.path Einfügen:

sys.path.insert(0, './lib') 
import BoxTime 
+6

Das ist großartig, wenn Sie aus irgendeinem Grund die Datei __init__.py nicht erstellen können oder wollen. – jpihl

+1

scheint nicht für mich zu arbeiten ('Kein Modul ..' Fehler) – minsk

+1

Es funktioniert, wenn Sie Python aus dem "Projekt" -Verzeichnis ausführen. Das "." wird relativ zu Ihrem aktuellen Arbeitsverzeichnis interpretiert, nicht relativ zu dem Verzeichnis, in dem die Datei ausgeführt wird. Sagen Sie "cd/data", "python ../ project/tester.py". Dann wird es nicht funktionieren. – morningstar

0

versuchen Sie dies:

from lib import BoxTime

+1

ohne Erklärung ist das nicht sehr nützlich. –

6

ich dies tun, die im Grunde alle Fälle abdeckt (stellen Sie sicher, dass Sie __init__.py in relativ/Pfad haben/to/your/lib/Ordner):

import sys, os 
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/relative/path/to/your/lib/folder") 
import someFileNameWhichIsInTheFolder 
... 
somefile.foo() 


Beispiel:
Sie haben in Ihrem Projektordner:

/root/myproject/app.py 

Sie haben in einem anderen Projektordner:

/root/anotherproject/utils.py 
/root/anotherproject/__init__.py 

Sie wollen /root/anotherproject/utils.py verwenden und Foo-Funktion aufrufen, die in ihm ist.

So schreiben Sie in app.py:

import sys, os 
sys.path.append(os.path.dirname(os.path.realpath(__file__)) + "/../anotherproject") 
import utils 

utils.foo() 
+1

Wenn Sie 'os.path' verwenden, möchten Sie wahrscheinlich' os.path.join ((os.path.dirname (os.path.realpath (__ file __)), '..', 'anotherproject') '' verwenden anstatt das '/' in Ihrer Pfadverkettung fest zu codieren. – cowbert

0

Erstellen Sie eine leere Datei __init__.py im Unterverzeichnis/lib. am Beginn des Hauptcode Und füge

from __future__ import absolute_import 

dann

import lib.BoxTime as BT 
... 
BT.bt_function() 

oder besser

from lib.BoxTime import bt_function 
... 
bt_function() 
Verwandte Themen