2012-01-28 7 views
49

jestem prawdopodobnie brakuje coś oczywistego, ale w każdym razie:pakiety przywozu w Pythonie

Podczas importowania pakietu jak os W Pythonie można użyć dowolnego submodules/podpakiety poza zakład. Na przykład to działa:

>>> import os 
>>> os.path.abspath(...) 

Jednak mam swój własny pakiet, który ma następującą strukturę:

FooPackage/ 
    __init__.py 
    foo.py 

i tu ta sama logika nie działa:

>>> import FooPackage 
>>> FooPackage.foo 
AttributeError: 'module' object has no attribute 'foo' 

Co mam robić źle?

Odpowiedz

29

trzeba importować submodule:

import FooPackage.foo 

Co robisz szuka foo w FooPackage/__init__.py. Możesz go rozwiązać, umieszczając import FooPackage.foo as foo (lub from . import foo) w FooPackage/__init__.py, a następnie Python będzie mógł tam znaleźć foo. Ale polecam użyć mojej pierwszej sugestii.

+4

Jak rozumiem, nie było pytanie, jak zaimportować submoduł - dlatego można uzyskać dostęp do modułu częściowego bez importowania tego modułu, a także jak zaimplementować coś podobnego. Edycja: Jednak twoja odpowiedź zadziała – pycoder112358

55

Podczas importowania FooPackage, Python przeszukuje katalogi na PYTHONPATH aż znajdzie plik o nazwie FooPackage.py lub katalog o nazwie FooPackage zawierającą plik o nazwie __init__.py. Jednak po znalezieniu katalogu pakietów, robi to , a nie, a następnie skanuje ten katalog i automatycznie importuje wszystkie pliki .py.

Istnieją dwa powody takiego zachowania. Pierwszy polega na tym, że import modułu wykonuje kod Pythona, co może wymagać czasu, pamięci lub efektów ubocznych. Więc możesz zaimportować a.b.c.d bez konieczności importowania całego ogromnego pakietu a. Do projektanta pakietów należy decyzja, czy plik A-__init__.py wyraźnie importuje swoje moduły i podpakiety, dzięki czemu są one zawsze dostępne lub pozostawia programowi klienta możliwość wybrania i wybrania załadowanego pliku.

Drugi to nieco bardziej subtelny, a także showstopper. Bez jawnej instrukcji importowania (w wersji FooPackage/__init__.py lub w programie klienta) Python nie musi wiedzieć, jaką nazwę ma zaimportować jako foo.py jako. W przypadku niewrażliwego systemu plików (takich jak używane w systemie Windows), może to stanowić moduł o nazwie foo, Foo, FOO, fOo, foO, FoO, FOo lub fOO. Wszystkie te są poprawnymi, odrębnymi identyfikatorami Pythona, więc Python nie ma wystarczających informacji z samego pliku, aby wiedzieć, co masz na myśli. W związku z tym, aby zachować spójne działanie we wszystkich systemach, wymagane jest wyraźne polecenie importowania w celu wyjaśnienia nazwy, nawet w systemach plików, w których dostępne są pełne informacje o przypadku.

9

Musisz dodać from . import foo do pliku __init__.py w paczce.

+1

(Ta informacja znajdowała się w innych już opublikowanych odpowiedziach, ale musiałaś je trochę przeczytać, dlatego opublikowałem ją ponownie jako prostą odpowiedź na pytanie.) –

+0

Lepiej używać zamiast tego "__all__ = [" foo "] –

-1

Możesz zaimportować pakiet z biblioteki za pomocą instrukcji import.

składnia: import module_name

 ex: import math 

Można importować tylko specyficzny sposób utworzyć pakiet za pomocą składni blow

składnia: od module_name importowej FUNCTION_NAME

 ex: from math import radians 
1

Istnieje kilka ważnych nieporozumień, którymi należy się zająć, szczególnie w odniesieniu do terminologii. Po pierwsze, zazwyczaj, gdy sądzisz, że importujesz plik package w pythonie, importowany plik to module. Powinieneś używać terminu package, gdy myślisz o podstrukturze systemu plików, która pomaga w organizacji kodu. Ale z perspektywy kodu, za każdym razem, gdy importujesz plik package, Python traktuje go jako moduł. Wszystkie pakiety są modułami. Nie wszystkie moduły są pakietami. Moduł z atrybutem __path__ jest traktowany jako pakiet.

Możesz sprawdzić, czy os jest modułem. Aby to potwierdzić, można zrobić:

import os 
print(type(os)) # will print: <type 'module'> 

W przykładzie, kiedy robisz import FooPackage, FooPackage traktuje i uważana za zbyt moduł, a jego atrybutami (funkcje, klasy, itd) są podobno zdefiniowane w __init__.py . Ponieważ twój __init__.py jest pusty, nie może znaleźć foo.

Poza instrukcjami import nie można używać notacji '.' do adresowania modułów wewnątrz modułów. Jedyny wyjątek ma miejsce, jeśli plik module zostanie zaimportowany do pliku docelowego rodzica o nazwie __init__.py. Żeby było jasne, zróbmy kilka przykładów tutaj:

rozważyć swoją pierwotną strukturę:

FooPackage/ 
    __init__.py 
    foo.py 

Przypadek 1: __init__.py jest pusty plik

#FooPackage imported as a module 
import FooPackage 

#foo is not a name defined in `__init__.py`. Error 
FooPackage.foo 

#FooPackage.foo imported as a module 
import FooPackage.foo 

#Error, foo has not been imported. To be able to use foo like this, 
#you need to do: import FooPackage.foo as foo 
foo.anything 

#Not error, if anything is defined inside foo.py 
FooPackage.foo.anything 

Przypadek 2: __init__.py ma linię import foo w tym:

import FooPackage 

#Now this is good. `foo` is sort of considered to be an attribute of 
#FooPackage 
FooPackage.foo 

Załóżmy teraz, że foo nie jest już module, ale jest to function zdefiniowane w __init__.py. jeśli wykonasz import FooPackage.foo, wyświetli się komunikat, że foo nie jest modułem.