Co to jest init.py za co?

Do czego służy __init__.py w katalogu źródłowym Pythona?

 1492
Author: guaka, 2009-01-15

11 answers

To część pakietu. Oto dokumentacja.

Pliki __init__.py są wymagane, aby Python traktował katalogi jako zawierające Pakiety; ma to na celu uniemożliwienie katalogom o wspólnej nazwie, takim jak string, niezamierzonego ukrywania poprawnych modułów, które pojawią się później (głębiej) na ścieżce wyszukiwania modułów. W najprostszym przypadku __init__.py może być tylko pustym plikiem, ale może również wykonać kod inicjalizacyjny dla pakietu lub ustawić zmienną __all__, opisaną później.

 1030
Author: Loki,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-02-05 16:23:19

Pliki o nazwie __init__.py są używane do oznaczania katalogów na dysku jako katalogów pakietów Pythona. Jeśli masz pliki

mydir/spam/__init__.py
mydir/spam/module.py

I mydir jest na twojej ścieżce, możesz zaimportować kod w module.py jako

import spam.module

Lub

from spam import module

Jeśli usuniesz plik __init__.py, Python nie będzie już szukał podmoduł w tym katalogu, więc próby zaimportowania modułu nie powiodą się.

Plik __init__.py jest zwykle pusty, ale można go użyć do eksportu wybranych części pakietu pod więcej wygodna nazwa, funkcje wygody itp. Biorąc pod uwagę powyższy przykład, zawartość modułu init może być dostępna jako

import spam

Na podstawie tego

 615
Author: caritos,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-28 16:01:34

Oprócz etykietowania katalogu jako pakietu Pythona i definiowania __all__, __init__.py pozwala na zdefiniowanie dowolnej zmiennej na poziomie pakietu. jest to często wygodne, jeśli pakiet definiuje coś, co będzie często importowane, w sposób podobny do API. Ten wzór Promuje przestrzeganie filozofii Pythonicznej "płaskie jest lepsze niż zagnieżdżone".

Przykład

Oto przykład z jednego z moich projektów, w którym często importuję sessionmaker o nazwie Session do wejdź w interakcję z moją bazą danych. Napisałem pakiet "baza danych" z kilkoma modułami:

database/
    __init__.py
    schema.py
    insertions.py
    queries.py

Mój __init__.py zawiera następujący kod:

import os

from sqlalchemy.orm import sessionmaker
from sqlalchemy import create_engine

engine = create_engine(os.environ['DATABASE_URL'])
Session = sessionmaker(bind=engine)

Ponieważ definiuję Session tutaj, mogę rozpocząć nową sesję używając składni poniżej. Kod ten byłby taki sam, wykonywany z wewnątrz lub poza katalogiem pakietów "database".

from database import Session
session = Session()

Oczywiście jest to mała wygoda -- alternatywą byłoby zdefiniowanie Session w nowym Pliku jak "create_session.py" w moim pakiecie bazy danych i rozpocznij nowe sesje używając:

from database.create_session import Session
session = Session()

Czytaj dalej

Jest dość ciekawy wątek dotyczący odpowiednich zastosowań __init__.py tutaj:

Http://www.reddit.com/r/Python/comments/1bbbwk/whats_your_opinion_on_what_to_include_in_init_py/

Większość uważa, że pliki powinny być bardzo cienkie, aby uniknąć naruszania filozofii "explicit is better than implicit".

 374
Author: Nathan Gould,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-09-24 17:55:49

Istnieją 2 główne powody __init__.py

  1. Dla wygody: inni użytkownicy nie będą musieli znać dokładnej lokalizacji Twoich funkcji w hierarchii pakietów.

    your_package/
      __init__.py
      file1.py/
      file2.py/
        ...
      fileN.py
    
    # in __init__.py
    from file1 import *
    from file2 import *
    ...
    from fileN import *
    
    # in file1.py
    def add():
        pass
    

    Wtedy inni mogą wywołać add () przez

    from your_package import add
    

    Bez znajomości file1, jak

    from your_package.file1 import add
    
  2. Jeśli chcesz, aby coś zostało zainicjowane; na przykład, logowanie (które powinno być umieszczone na najwyższym poziomie):

    import logging.config
    logging.config.dictConfig(Your_logging_config)
    
 113
Author: flycee,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-01-02 14:29:05

Plik __init__.py sprawia, że Python traktuje katalogi zawierające go jako moduły.

Co więcej, jest to pierwszy plik, który zostanie załadowany do modułu, więc możesz go użyć do wykonania kodu, który chcesz uruchomić za każdym razem, gdy moduł jest ładowany, lub określić podmoduły, które mają być eksportowane.

 87
Author: Can Berk Güder,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-01-15 20:22:58

Od wersji Pythona 3.3, __init__.py nie jest już wymagane definiowanie katalogów jako importowalnych pakietów Pythona.

Sprawdź PEP 420: Implicit Namespace Packages :

Natywne wsparcie dla katalogów pakietów, które nie wymagają plików znaczników __init__.py i mogą automatycznie obejmować wiele segmentów ścieżek (inspirowane różnymi podejściami stron trzecich do przestrzeni nazw pakietów, jak opisano w PEP 420)

Oto test:

$ mkdir -p /tmp/test_init
$ touch /tmp/test_init/module.py /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
├── module.py
└── __init__.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

$ rm -f /tmp/test_init/__init__.py
$ tree -at /tmp/test_init
/tmp/test_init
└── module.py
$ python3

>>> import sys
>>> sys.path.insert(0, '/tmp')
>>> from test_init import module
>>> import test_init.module

References:
https://docs.python.org/3/whatsnew/3.3.html#pep-420-implicit-namespace-packages
https://www.python.org/dev/peps/pep-0420/
/ align = "left" / init__.py nie jest wymagane dla pakietów w Pythonie 3?

 48
Author: zeekvfu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41

W Pythonie definicja pakietu jest bardzo prosta. Podobnie jak Java struktura hierarchiczna i struktura katalogów są takie same. Ale musisz mieć __init__.py w opakowaniu. Wyjaśnię plik __init__.py poniższym przykładem:

package_x/
|--  __init__.py
|--    subPackage_a/
|------  __init__.py
|------  module_m1.py
|--    subPackage_b/
|------  __init__.py
|------  module_n1.py
|------  module_n2.py
|------  module_n3.py

__init__.py może być pusty, o ile istnieje. Oznacza to, że katalog powinien być traktowany jako pakiet. Oczywiście __init__.py może również ustawić odpowiednią treść.

Jeśli dodamy funkcję w module_n1:

def function_X():
    print "function_X in module_n1"
    return

Po przebieg:

>>>from package_x.subPackage_b.module_n1 import function_X
>>>function_X()

function_X in module_n1 

Następnie podążaliśmy za pakietem hierarchii i nazwaliśmy module_n1 funkcją. Możemy użyć __init__.py w subPackage_b w następujący sposób:

__all__ = ['module_n2', 'module_n3']

Po uruchomieniu:

>>>from package_x.subPackage_b import * 
>>>module_n1.function_X()

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named module_n1

Stąd używanie * importowanie, pakiet modułów podlega zawartości __init__.py.

 46
Author: Marcus Thornton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-03-17 18:20:39

__init__.py będzie traktował katalog, w którym się znajduje, jako moduł do ładowania.

Dla osób, które wolą czytać kod, umieszczam tutaj Two-Bit alchemist ' s komentarz.

$ find /tmp/mydir/
/tmp/mydir/
/tmp/mydir//spam
/tmp/mydir//spam/__init__.py
/tmp/mydir//spam/module.py
$ cd ~
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
>>> module.myfun(3)
9
>>> exit()
$ 
$ rm /tmp/mydir/spam/__init__.py*
$ 
$ python
>>> import sys
>>> sys.path.insert(0, '/tmp/mydir')
>>> from spam import module
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ImportError: No module named spam
>>> 
 36
Author: B.Mr.W.,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:41

Co to jest __init__.py używany do?

Podstawowym zastosowaniem __init__.py jest inicjalizacja pakietów Pythona. Najprostszym sposobem na zademonstrowanie tego jest przyjrzenie się strukturze standardowego modułu Pythona.

package/
    __init__.py
    file.py
    file2.py
    file3.py
    subpackage/
        __init__.py
        submodule1.py
        submodule2.py

Jak widać w powyższej strukturze włączenie pliku __init__.py do katalogu wskazuje interpreterowi Pythona, że katalog powinien być traktowany jak pakiet Pythona

Co wchodzi __init__.py?

__init__.py może być pusty plik, ale jest on często używany do wykonania konfiguracji wymaganej dla pakietu(import rzeczy, załadowanie rzeczy do path, itd.).

Jedną z najczęstszych rzeczy do zrobienia w __init__.py jest importowanie wybranych klas, funkcji itp.do poziomu pakietu, aby można było je wygodnie importować z pakietu.

W powyższym przykładzie możemy powiedzieć, że file.py ma akta klasowe. Więc bez czegokolwiek w naszej __init__.py zaimportowałbyś z tą składnią:

from package.file import File

Można jednak zaimportować plik do swojego __init__.py aby go udostępnić na poziomie pakietu:

# in your __init__.py
from file import File

# now import File from package
from package import File

Kolejną rzeczą do zrobienia jest na poziomie pakietu udostępnienie podpakietów / modułów ze zmienną __all__. Gdy interpeter widzi zmienną __all__ zdefiniowaną w __init__.py, importuje Moduły wymienione w zmiennej __all__, gdy to zrobisz:

from package import *

__all__ jest to lista zawierająca nazwy modułów, które chcesz zaimportować za pomocą import*, więc patrząc na nasz powyższy przykład ponownie, jeśli chcemy zaimportować moduły podrzędne w zmienna __all__ w subpackage/__init__.py będzie:

__all__ = ['submodule1', 'submodule2']

Ze zmienną __all__ wypełnioną w ten sposób, gdy wykonasz

from subpackage import *

Importowałby submodule1 i submodule2.

Jak widać __init__.py może być bardzo przydatny oprócz swojej podstawowej funkcji wskazywania, że katalog jest modułem.

Numer referencyjny

 33
Author: Chirag Maliwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-03-03 04:40:14

Ułatwia importowanie innych plików Pythona. Po umieszczeniu tego pliku w katalogu (powiedzmy rzeczy)zawierającym inne pliki py, możesz zrobić coś takiego jak import rzeczy.inne.

root\
    stuff\
         other.py

    morestuff\
         another.py

Bez tego __init__.py wewnątrz katalogu rzeczy, nie można importować other.py, ponieważ Python nie wie, gdzie znajduje się kod źródłowy rzeczy i nie jest w stanie rozpoznać go jako pakietu.

 25
Author: Epitaph,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-06-08 10:45:40

Chociaż Python działa bez pliku __init__.py, nadal powinieneś go dołączyć.

Określa, że pakiet powinien być traktowany jako moduł, więc dołącz go (nawet jeśli jest pusty).

Istnieje również przypadek, w którym możesz użyć pliku __init__.py:

wyobraź sobie, że masz następującą strukturę plików:

main_methods 
    |- methods.py

I methods.py zawierały to:

def foo():
    return 'foo'

Aby użyć foo(), potrzebujesz jednego z następujących elementów:

from main_methods.methods import foo # Call with foo()
from main_methods import methods # Call with methods.foo()
import main_methods.methods # Call with main_methods.methods.foo()

Maybe tam musisz (lub chcesz) przechowywać methods.py wewnątrz main_methods (na przykład runtimes/dependencies), ale chcesz tylko zaimportować main_methods.


Jeśli zmieniłeś nazwę methods.py na __init__.py, możesz użyć foo() po prostu importując main_methods:

import main_methods
print(main_methods.foo()) # Prints 'foo'

To działa, ponieważ {[4] } jest traktowany jako część pakietu.


Niektóre pakiety Pythona faktycznie to robią. Przykładem jest JSON, gdzie uruchamianie import json jest faktycznie importowaniem __init__.py z json pakietu ( zobacz struktura plików pakietu tutaj):

Kod źródłowy: Lib/json/__init__.py

 8
Author: Simon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-18 07:48:38