6. Moduły¶
Jeśli wyjdziesz z interpretera Pythona i wejdziesz do niego z powrotem, zauważysz, że straciłeś(-łaś) definicje, które zrobiłeś(-łaś) (funkcje i zmienne). Z tego powodu, jeśli chcesz napisać nieco dłuższy program, lepiej będzie użyć edytora tekstu, aby przygotować wejście dla interpretera i uruchomić go z tym plikiem jako wejściem. Znane jest to jako tworzenie „skryptu”. Kiedy twój program staje się dłuższy, możesz podzielić go na kilka plików dla łatwiejszego utrzymania. Możesz chcieć też użyć przydatnej funkcji, którą napisałeś, w kilku programach, bez kopiowania jej definicji do każdego programu.
By to zapewnić, Python ma możliwość umieszczania definicji w pliku i używania ich w skrypcie lub w interaktywnej instancji interpretera. Taki plik nazywa się modułem; definicje z modułu mogą być importowane do innych modułów lub do modułu main (zbiór zmiennych, do których masz dostęp w skrypcie wykonywanym na najwyższym poziomie i w trybie kalkulatora).
Moduł to plik zawierający definicje i instrukcje Pythona. Nazwą pliku jest nazwa modułu z dodanym sufiksem .py
. Wewnątrz modułu, jego nazwa (jako ciąg znaków) jest dostępna jako wartość zmiennej globalnej __name__
. Na przykład użyj swojego ulubionego edytora tekstu, by stworzyć plik o nazwie fibo.py
w bieżącym katalogu, z następującą zawartością:
# Fibonacci numbers module
def fib(n): # write Fibonacci series up to n
a, b = 0, 1
while a < n:
print(a, end=' ')
a, b = b, a+b
print()
def fib2(n): # return Fibonacci series up to n
result = []
a, b = 0, 1
while a < n:
result.append(a)
a, b = b, a+b
return result
Wejdź w interpreter Pythona i zaimportuj ten moduł następującą komendą:
>>> import fibo
Ta komenda nie umieszcza nazw funkcji określonych w fibo
bezpośrednio w bieżącej tabeli symboli; umieszcza ona tam tylko nazwę modułu fibo
. Używając nazwy modułu możesz użyć funkcji:
>>> fibo.fib(1000)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377 610 987
>>> fibo.fib2(100)
[0, 1, 1, 2, 3, 5, 8, 13, 21, 34, 55, 89]
>>> fibo.__name__
'fibo'
Jeśli zamierzasz używać funkcji często, możesz przypisać ją do lokalnej nazwy:
>>> fib = fibo.fib
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
6.1. Więcej o modułach¶
Moduł może zawierać zarówno wykonywalne instrukcje jak i definicje funkcji. Instrukcje mają inicjalizować moduł. Są wykonywane tylko za pierwszym razem, gdy nazwa modułu zostanie napotkana w instrukcji importu. 1 (Są one również wykonywane, jeśli plik jest wykonywany jako skrypt.)
Każdy moduł ma swoją własną tablicę symboli, która jest używana jako globalna tablica symboli przez wszystkie funkcje zdefiniowane w tym module. Tak więc autor modułu może używać globalnych zmiennych nie martwiąc się o przypadkowe konflikty z globalnymi zmiennymi użytkownika. Z drugiej strony, jeśli wiesz co robisz, możesz odnosić się do globalnych zmiennych modułu tą samą notacją, którą używa się do odniesień do jego funkcji, nazwamodułu.nazwalementu
.
Moduły mogą importować inne moduły. Zwyczajowo (nieobowiązkowo) umieszcza się wszystkie instrukcje import
na początku modułu (lub skryptu). Zaimportowane nazwy modułów są umieszczane w globalnej tablicy symboli modułu importującego.
Istnieje wariant instrukcji import
, który importuje nazwy z modułu bezpośrednio do tablicy symboli modułu importującego. Na przykład:
>>> from fibo import fib, fib2
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Nie wprowadza to nazwy modułu, z którego wzięte są importy do lokalnej tablicy symboli (więc w przykładzie fibo
nie jest zdefiniowane).
Jest również wariant importujący wszystkie nazwy definiowane przez moduł:
>>> from fibo import *
>>> fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Importuje to wszystkie nazwy z wyjątkiem tych zaczynających się od podkreślenia (_
). W większości przypadków programiści Pythona nie używają tego udogodnienia, ponieważ wprowadza ono nieznany zestaw nazw do interpretera, być może ukrywając niektóre już zdefiniowane rzeczy.
Zauważ, że ogólnie praktyka importowania *
z modułu lub pakietu jest niemile widziana, ponieważ często powoduje, że kod jest mało czytelny. Można jej jednak używać do oszczędzania pisania w sesjach interaktywnych.
Jeżeli po nazwie modułu następuje as
, to nazwa następująca po as
jest powiązana bezpośrednio z importowanym modułem.
>>> import fibo as fib
>>> fib.fib(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
W praktyce jest to importowanie modułu w taki sam sposób, jak robi to import fibo
, z tą różnicą, że jest on dostępny jako fib
.
Można go również użyć przy użyciu from
z podobnym efektem:
>>> from fibo import fib as fibonacci
>>> fibonacci(500)
0 1 1 2 3 5 8 13 21 34 55 89 144 233 377
Informacja
Ze względów wydajnościowych każdy moduł jest importowany tylko raz dla sesji interpretera. W związku z tym jeśli zmienisz swoje moduły, musisz zrestartować interpreter – lub, jeśli to tylko jeden moduł, który chcesz testować interaktywnie, użyj importlib.reload()
, na przykład import importlib; importlib.reload(modulename)
.
6.1.1. Wykonywanie modułów jako skryptów¶
Kiedy uruchamiasz moduł Pythona:
python fibo.py <arguments>
kod w module zostanie wykonany, tak jakbyś go zaimportował, ale z __name__
ustawionym na "__main__"
. To oznacza, że dodając ten kod na końcu swojego modułu:
if __name__ == "__main__":
import sys
fib(int(sys.argv[1]))
możesz uczynić plik używalnym zarówno jako skrypt oraz jako importowalny moduł, ponieważ kod, który parsuje linię komend uruchamia się tylko jeśli moduł jest wykonywany jako plik „główny”:
$ python fibo.py 50
0 1 1 2 3 5 8 13 21 34
Jeśli moduł jest zaimportowany, kod nie jest uruchamiany:
>>> import fibo
>>>
Często się z tego korzysta, aby dodać wygodny interfejs użytkownika do modułu lub na potrzeby testów (uruchomienie modułu jako skryptu wykonuje zestaw testów).
6.1.2. Ścieżka wyszukiwania modułów¶
When a module named spam
is imported, the interpreter first searches for
a built-in module with that name. These module names are listed in
sys.builtin_module_names
. If not found, it then searches for a file
named spam.py
in a list of directories given by the variable
sys.path
. sys.path
is initialized from these locations:
Katalog zawierający skrypt wejściowy (lub bieżący katalog, jeśli plik nie jest określony).
PYTHONPATH
(lista nazw katalogów o takiej samej składni jak zmienna shellPATH
).The installation-dependent default (by convention including a
site-packages
directory, handled by thesite
module).
Informacja
W systemach plików wspierających dowiązania symboliczne, katalog zawierający skrypt wejściowy jest wyliczany po rozwiązaniu dowiązania symbolicznego. Innymi słowy katalog zawierający dowiązanie symboliczne nie jest dodany do ścieżki wyszukiwania modułów.
Po inicjalizacji programy pythonowe mogą modyfikować sys.path
. Katalog zwierający uruchamiany skrypt jest umieszczony na początku ścieżki wyszukiwania, przed ścieżką biblioteki standardowej. To znaczy, że skrypty w tym katalogu zostaną załadowane zamiast modułów o tej samej nazwie w katalogu biblioteki. Jest to błąd, o ile taka zamiana jest zamierzona. Patrz sekcja Moduły standardowe po więcej informacji.
6.1.3. „Skompilowane” pliki Pythona¶
Aby przyspieszyć ładowanie modułów, Python cache’uje skompilowaną wersję każdego modułu w katalogu __pycache__
pod nazwą module.wersja.pyc
, gdzie wersja koduje format skompilowanego pliku; zazwyczaj zawiera numer wersji Pythona. Na przykład w wydaniu CPythona 3.3 skompilowana wersja spam.py zostałaby zcache’owana jako __pycache__/spam.cpython-33.pyc
. Ta konwencja nazw pozwala na współistnienie skompilowanych modułów z różnych wydań i wersji Pythona.
Python porównuje datę modyfikacji źródła ze skompilowaną wersją, aby ustalić, czy jest przeterminowana i powinna zostać zrekompilowana. To całkowicie automatyczny proces. Skompilowane moduły są niezależne od platformy, więc ta sama biblioteka może być współdzielona pomiędzy systemami z innymi architekturami.
Python nie sprawdza cache’u w dwóch przypadkach. Po pierwsze zawsze rekompiluje i nie zapisuje wyniku dla modułu załadowanego bezpośrednio z linii komend. Po drugie nie sprawdza cache’u, kiedy nie ma modułu źródłowego. Dla wsparcia dystrybucji bez źródła (tylko kompilowany), skompilowany moduł musi być w katalogu źródłowym i nie może być modułu źródłowego.
Wskazówki dla ekspertów:
Możesz użyć przełączników
-O
lub-OO
na komendziepython
, aby zmniejszyć rozmiar skompilowanego modułu. Przełącznik-O
usuwa instrukcje assert. Przełącznik-OO
usuwa zarówno instrukcje assert jak i docstringi. Jako że niektóre programy mogą polegać na dostępności powyższych, powinieneś(-nnaś) używać tylko jeśli wiesz, co robisz. „Zoptymalizowane” moduły mają tagopt-
i zazwyczaj są mniejsze. Przyszłe wydania mogą zmienić efekty optymalizacji.Program nie wykonuje się ani chwili szybciej, gdy jest czytany z pliku
.pyc
niż gdy jest czytany z pliku.py
. Jedyna rzecz, która jest szybsza w plikach.pyc
to szybkość, w jakiej są one ładowane.The module
compileall
can create .pyc files for all modules in a directory.There is more detail on this process, including a flow chart of the decisions, in PEP 3147.
6.2. Moduły standardowe¶
Python comes with a library of standard modules, described in a separate
document, the Python Library Reference („Library Reference” hereafter). Some
modules are built into the interpreter; these provide access to operations that
are not part of the core of the language but are nevertheless built in, either
for efficiency or to provide access to operating system primitives such as
system calls. The set of such modules is a configuration option which also
depends on the underlying platform. For example, the winreg
module is only
provided on Windows systems. One particular module deserves some attention:
sys
, which is built into every Python interpreter. The variables
sys.ps1
and sys.ps2
define the strings used as primary and secondary
prompts:
>>> import sys
>>> sys.ps1
'>>> '
>>> sys.ps2
'... '
>>> sys.ps1 = 'C> '
C> print('Yuck!')
Yuck!
C>
These two variables are only defined if the interpreter is in interactive mode.
The variable sys.path
is a list of strings that determines the interpreter’s
search path for modules. It is initialized to a default path taken from the
environment variable PYTHONPATH
, or from a built-in default if
PYTHONPATH
is not set. You can modify it using standard list
operations:
>>> import sys
>>> sys.path.append('/ufs/guido/lib/python')
6.3. The dir()
Function¶
The built-in function dir()
is used to find out which names a module
defines. It returns a sorted list of strings:
>>> import fibo, sys
>>> dir(fibo)
['__name__', 'fib', 'fib2']
>>> dir(sys)
['__breakpointhook__', '__displayhook__', '__doc__', '__excepthook__',
'__interactivehook__', '__loader__', '__name__', '__package__', '__spec__',
'__stderr__', '__stdin__', '__stdout__', '__unraisablehook__',
'_clear_type_cache', '_current_frames', '_debugmallocstats', '_framework',
'_getframe', '_git', '_home', '_xoptions', 'abiflags', 'addaudithook',
'api_version', 'argv', 'audit', 'base_exec_prefix', 'base_prefix',
'breakpointhook', 'builtin_module_names', 'byteorder', 'call_tracing',
'callstats', 'copyright', 'displayhook', 'dont_write_bytecode', 'exc_info',
'excepthook', 'exec_prefix', 'executable', 'exit', 'flags', 'float_info',
'float_repr_style', 'get_asyncgen_hooks', 'get_coroutine_origin_tracking_depth',
'getallocatedblocks', 'getdefaultencoding', 'getdlopenflags',
'getfilesystemencodeerrors', 'getfilesystemencoding', 'getprofile',
'getrecursionlimit', 'getrefcount', 'getsizeof', 'getswitchinterval',
'gettrace', 'hash_info', 'hexversion', 'implementation', 'int_info',
'intern', 'is_finalizing', 'last_traceback', 'last_type', 'last_value',
'maxsize', 'maxunicode', 'meta_path', 'modules', 'path', 'path_hooks',
'path_importer_cache', 'platform', 'prefix', 'ps1', 'ps2', 'pycache_prefix',
'set_asyncgen_hooks', 'set_coroutine_origin_tracking_depth', 'setdlopenflags',
'setprofile', 'setrecursionlimit', 'setswitchinterval', 'settrace', 'stderr',
'stdin', 'stdout', 'thread_info', 'unraisablehook', 'version', 'version_info',
'warnoptions']
Without arguments, dir()
lists the names you have defined currently:
>>> a = [1, 2, 3, 4, 5]
>>> import fibo
>>> fib = fibo.fib
>>> dir()
['__builtins__', '__name__', 'a', 'fib', 'fibo', 'sys']
Note that it lists all types of names: variables, modules, functions, etc.
dir()
does not list the names of built-in functions and variables. If you
want a list of those, they are defined in the standard module
builtins
:
>>> import builtins
>>> dir(builtins)
['ArithmeticError', 'AssertionError', 'AttributeError', 'BaseException',
'BlockingIOError', 'BrokenPipeError', 'BufferError', 'BytesWarning',
'ChildProcessError', 'ConnectionAbortedError', 'ConnectionError',
'ConnectionRefusedError', 'ConnectionResetError', 'DeprecationWarning',
'EOFError', 'Ellipsis', 'EnvironmentError', 'Exception', 'False',
'FileExistsError', 'FileNotFoundError', 'FloatingPointError',
'FutureWarning', 'GeneratorExit', 'IOError', 'ImportError',
'ImportWarning', 'IndentationError', 'IndexError', 'InterruptedError',
'IsADirectoryError', 'KeyError', 'KeyboardInterrupt', 'LookupError',
'MemoryError', 'NameError', 'None', 'NotADirectoryError', 'NotImplemented',
'NotImplementedError', 'OSError', 'OverflowError',
'PendingDeprecationWarning', 'PermissionError', 'ProcessLookupError',
'ReferenceError', 'ResourceWarning', 'RuntimeError', 'RuntimeWarning',
'StopIteration', 'SyntaxError', 'SyntaxWarning', 'SystemError',
'SystemExit', 'TabError', 'TimeoutError', 'True', 'TypeError',
'UnboundLocalError', 'UnicodeDecodeError', 'UnicodeEncodeError',
'UnicodeError', 'UnicodeTranslateError', 'UnicodeWarning', 'UserWarning',
'ValueError', 'Warning', 'ZeroDivisionError', '_', '__build_class__',
'__debug__', '__doc__', '__import__', '__name__', '__package__', 'abs',
'all', 'any', 'ascii', 'bin', 'bool', 'bytearray', 'bytes', 'callable',
'chr', 'classmethod', 'compile', 'complex', 'copyright', 'credits',
'delattr', 'dict', 'dir', 'divmod', 'enumerate', 'eval', 'exec', 'exit',
'filter', 'float', 'format', 'frozenset', 'getattr', 'globals', 'hasattr',
'hash', 'help', 'hex', 'id', 'input', 'int', 'isinstance', 'issubclass',
'iter', 'len', 'license', 'list', 'locals', 'map', 'max', 'memoryview',
'min', 'next', 'object', 'oct', 'open', 'ord', 'pow', 'print', 'property',
'quit', 'range', 'repr', 'reversed', 'round', 'set', 'setattr', 'slice',
'sorted', 'staticmethod', 'str', 'sum', 'super', 'tuple', 'type', 'vars',
'zip']
6.4. Packages¶
Packages are a way of structuring Python’s module namespace by using „dotted
module names”. For example, the module name A.B
designates a submodule
named B
in a package named A
. Just like the use of modules saves the
authors of different modules from having to worry about each other’s global
variable names, the use of dotted module names saves the authors of multi-module
packages like NumPy or Pillow from having to worry about
each other’s module names.
Suppose you want to design a collection of modules (a „package”) for the uniform
handling of sound files and sound data. There are many different sound file
formats (usually recognized by their extension, for example: .wav
,
.aiff
, .au
), so you may need to create and maintain a growing
collection of modules for the conversion between the various file formats.
There are also many different operations you might want to perform on sound data
(such as mixing, adding echo, applying an equalizer function, creating an
artificial stereo effect), so in addition you will be writing a never-ending
stream of modules to perform these operations. Here’s a possible structure for
your package (expressed in terms of a hierarchical filesystem):
sound/ Top-level package
__init__.py Initialize the sound package
formats/ Subpackage for file format conversions
__init__.py
wavread.py
wavwrite.py
aiffread.py
aiffwrite.py
auread.py
auwrite.py
...
effects/ Subpackage for sound effects
__init__.py
echo.py
surround.py
reverse.py
...
filters/ Subpackage for filters
__init__.py
equalizer.py
vocoder.py
karaoke.py
...
When importing the package, Python searches through the directories on
sys.path
looking for the package subdirectory.
The __init__.py
files are required to make Python treat directories
containing the file as packages. This prevents directories with a common name,
such as string
, unintentionally hiding valid modules that occur later
on the module search path. In the simplest case, __init__.py
can just be
an empty file, but it can also execute initialization code for the package or
set the __all__
variable, described later.
Users of the package can import individual modules from the package, for example:
import sound.effects.echo
This loads the submodule sound.effects.echo
. It must be referenced with
its full name.
sound.effects.echo.echofilter(input, output, delay=0.7, atten=4)
An alternative way of importing the submodule is:
from sound.effects import echo
This also loads the submodule echo
, and makes it available without its
package prefix, so it can be used as follows:
echo.echofilter(input, output, delay=0.7, atten=4)
Yet another variation is to import the desired function or variable directly:
from sound.effects.echo import echofilter
Again, this loads the submodule echo
, but this makes its function
echofilter()
directly available:
echofilter(input, output, delay=0.7, atten=4)
Note that when using from package import item
, the item can be either a
submodule (or subpackage) of the package, or some other name defined in the
package, like a function, class or variable. The import
statement first
tests whether the item is defined in the package; if not, it assumes it is a
module and attempts to load it. If it fails to find it, an ImportError
exception is raised.
Contrarily, when using syntax like import item.subitem.subsubitem
, each item
except for the last must be a package; the last item can be a module or a
package but can’t be a class or function or variable defined in the previous
item.
6.4.1. Importing * From a Package¶
Now what happens when the user writes from sound.effects import *
? Ideally,
one would hope that this somehow goes out to the filesystem, finds which
submodules are present in the package, and imports them all. This could take a
long time and importing sub-modules might have unwanted side-effects that should
only happen when the sub-module is explicitly imported.
The only solution is for the package author to provide an explicit index of the
package. The import
statement uses the following convention: if a package’s
__init__.py
code defines a list named __all__
, it is taken to be the
list of module names that should be imported when from package import *
is
encountered. It is up to the package author to keep this list up-to-date when a
new version of the package is released. Package authors may also decide not to
support it, if they don’t see a use for importing * from their package. For
example, the file sound/effects/__init__.py
could contain the following
code:
__all__ = ["echo", "surround", "reverse"]
This would mean that from sound.effects import *
would import the three
named submodules of the sound.effects
package.
If __all__
is not defined, the statement from sound.effects import *
does not import all submodules from the package sound.effects
into the
current namespace; it only ensures that the package sound.effects
has
been imported (possibly running any initialization code in __init__.py
)
and then imports whatever names are defined in the package. This includes any
names defined (and submodules explicitly loaded) by __init__.py
. It
also includes any submodules of the package that were explicitly loaded by
previous import
statements. Consider this code:
import sound.effects.echo
import sound.effects.surround
from sound.effects import *
In this example, the echo
and surround
modules are imported in the
current namespace because they are defined in the sound.effects
package
when the from...import
statement is executed. (This also works when
__all__
is defined.)
Although certain modules are designed to export only names that follow certain
patterns when you use import *
, it is still considered bad practice in
production code.
Remember, there is nothing wrong with using from package import
specific_submodule
! In fact, this is the recommended notation unless the
importing module needs to use submodules with the same name from different
packages.
6.4.2. Intra-package References¶
When packages are structured into subpackages (as with the sound
package
in the example), you can use absolute imports to refer to submodules of siblings
packages. For example, if the module sound.filters.vocoder
needs to use
the echo
module in the sound.effects
package, it can use from
sound.effects import echo
.
You can also write relative imports, with the from module import name
form
of import statement. These imports use leading dots to indicate the current and
parent packages involved in the relative import. From the surround
module for example, you might use:
from . import echo
from .. import formats
from ..filters import equalizer
Note that relative imports are based on the name of the current module. Since
the name of the main module is always "__main__"
, modules intended for use
as the main module of a Python application must always use absolute imports.
6.4.3. Packages in Multiple Directories¶
Packages support one more special attribute, __path__
. This is
initialized to be a list containing the name of the directory holding the
package’s __init__.py
before the code in that file is executed. This
variable can be modified; doing so affects future searches for modules and
subpackages contained in the package.
While this feature is not often needed, it can be used to extend the set of modules found in a package.
Przypisy
- 1
In fact function definitions are also «statements» that are «executed»; the execution of a module-level function definition enters the function name in the module’s global symbol table.