Obtenez une compréhension abstraite des modules et des packages Python

introduction

À propos du système d'importation Python

Vous pouvez comprendre que, En s'éloignant des fichiers physiques et en réfléchissant un peu plus abstraitement, je pense que la visibilité de l'ensemble du système, comme les noms de modules, les importations relatives, le moment d'initialisation et la visibilité des noms, sera améliorée.

Notez que cet article ne couvre pas les ** packages d'espace de noms [^ 1] ** (car je ne les comprends pas).

Les références

J'ai parcouru la version v3.8.2 des deux.

environnement

Confirmé pour fonctionner avec Python v3.8.2. Vérifiez l'opération en tant que cas de test de pytest.

pip install pytest

Voir l'annexe pour vérifier le fonctionnement du pytest lui-même.

Aperçu

Un bref résumé des attributs:

__name__ __path__ __package__
module: module名 Aucun Nom du package parent
paquet: paquet名 paquetのパス paquet名

Qu'est-ce qu'un espace de noms?

C'est un concept couramment utilisé dans les langages de programmation ** Il s'agit d'une fonction qui vous permet d'utiliser des "noms" tels que le nom de variable "x" à différents endroits du programme avec des significations différentes sans crainte de collision. ** ** Par exemple, builtins.open et ʻos.open` sont tous deux des noms de fonction, mais parce qu'ils appartiennent à des espaces de noms différents. Peut être défini et utilisé comme différent. Le "module" décrit ci-dessous est cette ** unité d'espace de noms **.

Il existe un glossaire dans la documentation Python avec une entrée "namespace": https://docs.python.org/ja/3/glossary.html#term-namespace

Qu'est-ce qu'un module? Qu'est-ce qu'une importation?

Comme mentionné dans la présentation, un module est une ** unité d'espace de noms qui peut être importée **.

Unité d'espace de nom

Premièrement, parce qu'un module est une unité d'espace de noms, pour les modules m et n, le nom dans m`` x (= mx) et le nom dans n`` x (= nx ) Se distingue.

Tout le code fonctionne dans un certain espace de noms

Deuxièmement, moins consciemment, tout le code s'exécute dans un module, c'est-à-dire dans un espace de noms. Lorsque le code déclare et définit un nom, il est enregistré dans cet espace de noms. Immédiatement après le lancement de l'interpréteur Python, le code s'exécute dans l'espace de noms du module ** __ main__ **. Ceci est souvent utilisé pour ** une manière de savoir si un fichier .py a été lancé directement ou importé **.

Importation de module

Le module peut ensuite être importé. Importer un module signifie

--Trouver et mettre en cache le module et

C'est. Le document dit 2 étapes, mais si vous le considérez comme 3 étapes, l'unité de traitement est facile à comprendre. En termes simples, en important le module m comme ʻimport m`

Démarrez l'interpréteur Python en mode interactif et vérifiez-le. (Partiellement formé pour la lisibilité)

[.../module-experiments]$ python
Python 3.8.2 (default, Apr 18 2020, 18:08:23) 
[Clang 10.0.1 (clang-1001.0.46.4)] on darwin
Type "help", "copyright", "credits" or "license" for more information.

>>> print(__name__)
__main__

>>> import m
>>> sys.modules['m']
<module 'm' from '.../module-experiments/m.py'>
>>> m
<module 'm' from '.../module-experiments/m.py'>
>>> m.f
<function f at 0x108452b80>
>>> m.C
<class 'm.C'>

Vous pouvez voir que le module immédiatement après le démarrage est __main__. Vous pouvez également voir qu'en important «m», vous pouvez accéder à «m», «m.f» et «m.C».

Le module importé est mis en cache dans l'espace de noms local. Par conséquent, comme tout autre nom, un module importé dans une fonction n'est pas accessible par d'autres fonctions. Cependant, comme le cache est global, il est accessible.

Qu'est-ce qu'un package?

Un package est comme un module, sauf que vous pouvez y rechercher et importer des sous-modules. En utilisant des packages, vous pouvez créer une structure hiérarchique de modules.

Mettre tout simplement

Le nom du module (ou package) sera alors quelque chose comme ʻa.b.c séparé par des points. En important le module ʻa.b.c avec ʻimport a.b.c`

--Module d'importation (package) ʻa --Importer le sous-module (package)b (ʻa.b) dans l'espace de noms du module ʻa --Importer le sous-modulec (ʻa.b.c) dans l'espace de noms du module ʻa.b`

Cela vous permet d'accéder au module ʻa.b.c avec ʻa.b.c. ** Remarque: vous ne pourrez pas y accéder avec c. ** **

De plus, cette règle montre que les packages et les modules peuvent être importés de la même manière.

Bien sûr, vous ne pouvez pas accéder à ʻa.d ou ʻa.d.e immédiatement après avoir importé ʻa.b.c. Si vous faites ʻimport a.d.e ici, ʻa` existe dans le cache, donc

--Importer le sous-module (package) d (ʻa.d) dans l'espace de noms du module ʻa --Importer le sous-module ʻe (ʻa.d.e) dans l'espace de noms du module ʻa.d`

Cela n'arrive que, donc à ces points, le module est initialisé.

Un peu plus de détails

Techniquement, un package est un module qui a l'attribut __path__. Cet attribut est utilisé lors de la recherche de sous-packages. En d'autres termes, dans ʻimport a.b.c`,

--Trouver ʻa dans sys.path et importer --Trouver et importer ʻa.b depuis ʻa .__ path__ dans l'espace de noms du module ʻa --Trouver et importer ʻa.b.c depuis ʻa.b .__ path__ dans l'espace de noms du module ʻa.b`

Cela se produit.

Notez que le module contenant le package a l'attribut __name__. Pour les modules importés, cette valeur est le nom complet du module (tel que ʻa.b.c`).

Importation de package

Puisqu'un package est un module, il peut être importé avec l'instruction d'importation comme un module.

import ... as ...

Si l'instruction d'importation a une clause ʻas, le module importé lui-même est lié au nom ci-dessous ʻas. Par exemple, ʻimport a.b as b vous permet d'accéder au module ʻa.b directement avec le nom b.

A ce moment, puisque le module ʻa est chargé et initialisé, les informations sur le module ʻa (et, bien sûr, ʻa.b) sont mises en cache. Cependant, ʻa n'est pas lié à l'espace de noms.

>>> import sys
>>> import a.b as b
['/Users/shinsa/git/python-experiments/module-experiments/a']
a

>>> sys.modules['a']
<module 'a' from '/Users/shinsa/git/python-experiments/module-experiments/a/__init__.py'>
>>> sys.modules['a.b']
<module 'a.b' from '/Users/shinsa/git/python-experiments/module-experiments/a/b/__init__.py'>

>>> b
<module 'a.b' from '/Users/shinsa/git/python-experiments/module-experiments/a/b/__init__.py'>

>>> a
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
NameError: name 'a' is not defined

Le nom et le nom du module sont différents

Le nom du module vient immédiatement après ʻimport, et vous ne pouvez pas utiliser le nom défini à cet endroit. Par conséquent, juste parce que ʻimport a.b as b est utilisé, ʻimport a.b.c ne peut pas être écrit comme ʻimport b.c.

Importer avec la clause from

Cette forme d'importation prend le cas de «from a.b import c». c peut être un module, un package ou un nom. Le traitement suivant est effectué.

--Importer ʻa.b`. Cependant, le nom n'est pas lié.

Si la clause ʻasest spécifiée, au lieu de lierc dans l'exemple ci-dessus, elle est liée au nom spécifié dans la clause ʻas.

from ... import *

Si le nom à importer est *, c'est-à-dire from M import *, alors dans le module M

Sont tous liés dans l'espace de noms actuel.

Importation relative

Dans l'instruction from ... import ..., vous pouvez utiliser des représentations de package relatives dans la clause from. Par exemple, dans le script d'initialisation du package ʻa.b, ou dans le script du module ʻa.b.c

Représentez chacun. Vous pouvez avoir plus de points.

PEP 366

Les calculs relatifs des packages étaient basés sur l'attribut «name». Ensuite, par exemple, lorsque vous démarrez l'interpréteur avec python -m a.b.c, ʻa / b / c.py fonctionne comme un module main`. Pour cette raison, il y avait un problème qui, par exemple, «a.b.d» ne pouvait pas être importé relativement.

Les nouvelles versions de Python calculent désormais les importations relatives en fonction de l'attribut __package__, ce qui résout le problème de temps d'appel ci-dessus (PEP 366). Cependant, si vous le démarrez avec python <chemin> / a / b / c.py, vous devez définir les attributs manuellement.

Implémentation par défaut: système d'importation pour le système de fichiers

Jusqu'à présent, nous avons parlé des modules, des packages et de __path__ de manière abstraite. En d'autres termes, je ne parle pas du tout d'un système de fichiers spécifique. Dans les versions récentes, le système d'importation de Python est devenu un système très abstrait et puissant.

Par défaut, le système d'importation fonctionne sur un système de fichiers. Par défaut, les modules sont représentés par des fichiers .py et les packages par des répertoires. Les détails sont les suivants et on peut voir que cela correspond à la structure de données abstraite jusqu'à présent.

Inversement, par exemple, un système d'importation basé sur URI peut être implémenté, et le mécanisme de découverte de service peut être implémenté à l'aide du système d'importation de Python.

Enfin: un peu insatisfait

La documentation Python est déroutante car les informations sont dispersées un peu partout. C'est toujours compréhensible si vous le faites pour éviter la duplication d'informations, Au lieu de cela, chaque élément d'information est subtilement dupliqué mais dispersé. De plus, certaines informations sont obsolètes.

Recommended Posts

Obtenez une compréhension abstraite des modules et des packages Python
Paquets et modules Python
Apprenez à connaître les packages et les modules Python
Cours de base Python (14 modules et packages)
Les modules et packages en Python sont des "espaces de noms"
Compréhension complète du threading Python et du multitraitement
Organisez les modules et les packages Python dans le désordre
[Python] Une compréhension approximative des itérables, des itérateurs et des générateurs
Liste des modules python
Traitement asynchrone de Python ~ Comprenez parfaitement async et attendez ~
Python: obtenir une liste de méthodes pour un objet
[python] Obtenir le quotient et le surplus
Installation source et installation de Python
Compréhension complète du débogage Python
Débarrassez-vous des données sales avec Python et les expressions régulières
Exemple d'analyse HTTP GET et JSON avec Pepper Python
Construction d'environnement de python et opencv
L'histoire de Python et l'histoire de NaN
Paquets qui gèrent le MIDI avec Python midi et pretty_midi
mémorandum de multitraitement
Multitraitement instantané
Compréhension complète du threading Python et du multitraitement
Installer SciPy et matplotlib (Python)
Remarque: obtenez les premier et dernier éléments de Python OrderedDict de manière non destructive
Python et DB: comprendre le curseur DBI
Comment utiliser correctement le package de visualisation Python
[Python] Comment obtenir le premier et le dernier jour du mois
Obtenir les attributs d'un objet
Ceci et cela des propriétés python
[Python] Comprendre le potentiel_field_planning de Python Robotics
Obtenez et définissez la valeur du menu déroulant en utilisant Python et Selenium
Coexistence de Python2 et 3 avec CircleCI (1.0)
Résumé des index et des tranches Python
Obtenez le titre et la date de livraison de Yahoo! News en Python
Réputation des livres Python et des livres de référence
Obtenez des images d'OpenStreetMap et de la carte de l'Institut géographique avec Python + py-staticmaps
Obtenez une liste des packages installés dans l'environnement actuel avec python
Comparer la grammaire de base de Python et Go d'une manière facile à comprendre
Ouvrez un fichier Excel en Python et coloriez la carte du Japon
Obtenez des visites d'articles et des likes avec l'API Qiita + Python
Obtenez des images de la carte OpenStreetMap et de l'Institut géographique avec Python + staticmap
Obtenez et estimez la forme de la tête en utilisant Dlib et OpenCV avec python
Obtenez la valeur de retour d'un script shell externe (ls) avec python3
Explication de la création d'une application pour afficher des images et dessiner avec Python
Installation du code Visual Studio et installation de python
Une compréhension approximative de python-fire et un mémo
Environnement virtuel Python et packages sur Ubuntu
Extraction de tweet.js (json.loads et eval) (Python)
[Python] Empaquetez et distribuez vos propres modules
Connectez beaucoup de Python ou et et
[python] Obtenir une liste de variables d'instance
(Remarque) Mise à niveau en masse des packages installés en python
Résumé des modules et des classes dans Python-TensorFlow2-
[Python] Récupère le code de caractère du fichier
Introduction facile de la série python3 et d'OpenCV3
[Python] Diverses combinaisons de chaînes de caractères et de valeurs
[Python] Obtenir une liste de dossiers uniquement
Automatisation égale de l'installation de Python et PyPI
Débarrassez-vous des images DICOM en Python
Projet Euler # 1 "Multiple de 3 et 5" en Python
Python3> instruction pass> créer la plus petite classe / contenu des fonctions et des conditions> en pensant à un niveau abstrait
Obtenez le cours de l'action d'une entreprise japonaise avec Python et faites un graphique