Apprenez à connaître les packages et les modules Python

introduction

Lorsque vous touchez Python, vous ne pouvez pas vraiment faire la différence entre un module et un package. Surtout lors de l'utilisation d'un IDE appelé PyCharm, il se comporte étrangement.

Par conséquent, je voudrais résumer la lutte entre le package et le module afin que je puisse y revenir plus tard.

Touchez le module

Tout d'abord, touchons le module.

Qu'est-ce qu'un module?

Les modules représentent les «fichiers» en Python. En d'autres termes, si vous créez un fichier appelé ʻadd.py, ce sera un module appelé ʻadd.

En séparant les fonctions pour chaque module, il est possible d'éviter de gonfler les fonctions dans un seul fichier.

annuaire

Actuellement, nous utilisons une telle structure de répertoires.

Dans un répertoire appelé Python_Tutorial Contient les éléments suivants:

.
├── __pycache__
├── calc
│   ├── add.py
│   ├── calc_main.py
│   ├── mul.py
│   └── sub.py
└── main.py

Ecrivez le module dans le répertoire calc Essayez ensuite d'appeler un autre module de calcul depuis calc_main. Après cela, essayez d'utiliser main.py directement sous Python_Tutorial.

Préparation

add.py, mul.py, sub.py Préparer.

print('add.py')
print(__name__)


def add(x, y):
    return x + y


if __name__ == '__main__':
    print(add(10, 20))
print('sub.py')
print(__name__)


def sub(x, y):
    return x - y


if __name__ == '__main__':
    print(sub(10, 20))

print('mul.py')
print(__name__)


def mul(x, y):
    return x * y


if __name__ == '__main__':
    print(mul(10, 20))

Quel est le nom__

avec add.py etc.

if __name__ == '__main__':
    print(mul(10, 20))

Est attaché, mais qu'est-ce que c'est?

Il contient le "nom lors de l'exécution du fichier $ f $ .py".

Par exemple, essayez d'exécuter add.py. puis,

add.py
__main__
30

Est sortie.

En effet, il est exécuté à partir du fichier $ f $ = add, et main est défini dans name du fichier exécutable.

Sachez que name dans le fichier d'origine de l'exécution sera toujours main.

Essayez d'appeler le module

Essayez d'exécuter add, sub, mul du même répertoire depuis calc_main.py.

calc_main.py



import add

'''
add.py
add
30
'''
print(add.add(10, 20))

from sub import sub

'''
sub.py
sub
-10
'''
print(sub(20, 30))


from mul import *

'''
mul.py
mul
1500
'''
print(mul(30, 50))

Apparemment

importer le nom du fichier dans la même hiérarchie

Donc, il semble que d'autres fichiers peuvent être lus comme des modules.

Charger ajouter

import add

Lorsque vous le faites, deux impressions de add.py sont exécutées. Par conséquent, il semble qu'un traitement d'écriture solide tel que l'impression soit exécuté lorsque le module est chargé. De plus, name contient add. De cette façon, il semble que le nom du fichier soit entré tel quel lorsqu'il est appelé en tant que module au lieu du point de départ de l'exécution.

nom du fichier d'importation Puisqu'elle est lue, la fonction peut être utilisée dans add.add, qui est l'espace de noms du nom de fichier.

Cette notation semble sûre car la fonction ʻadd` protège les espaces de noms les uns des autres même s'ils sont dans d'autres fichiers!

Lire le sous

from sub import sub

Lorsque vous le faites, il semble que vous lisiez directement la fonction secondaire de sub.py. Il semble qu'il soit possible de le supprimer du module.

Cependant, il semble que la sous-fonction ne puisse pas être récupérée directement. Comme add.py

'''
sub.py
sub
'''

Est sortie, il semble donc que tout le contenu du sous-fichier sera exécuté au moment de from sub.

Chargement mul

from mul import *

Vous pouvez forcer tout le contenu du fichier mul dans l'espace de noms calc_main.py en masse.

En gros ** il semble préférable de ne pas utiliser **. La raison en est qu'il provoque un comportement inattendu tel que le remplacement lors de l'utilisation du même nom que d'autres modules.

Lire le résumé dans le même répertoire

nom du fichier d'importation

Peut-être le plus pratique.

Essayez plusieurs lectures

Ensuite, essayez plusieurs chargements. Je suis un arbre, comment il se comporte lorsque le même fichier est lu plusieurs fois

Structure du répertoire

Pour essayer plusieurs chargements a b Une configuration simple comme c semble être plus facile.

Essayez ce qui suit.

.
├── __pycache__
├── abc
│   ├── a.py
│   ├── ab.py
│   ├── abc_main.py
│   ├── b.py
│   ├── bc.py
│   ├── c.py
│   └── ca.py
├── calc
│   ├── __pycache__
│   │   ├── add.cpython-37.pyc
│   │   ├── mul.cpython-37.pyc
│   │   └── sub.cpython-37.pyc
│   ├── add.py
│   ├── calc_main.py
│   ├── mul.py
│   └── sub.py
├── main.py

Ajout du répertoire abc. ab.py lit les fichiers a et b en tant que modules.

Préparation

print('a file')

aa = 1
print('b file')

bb = 2
print('c file')

cc = 3

L'expérience commence par a, b et c.py comme décrit ci-dessus.

Préparation 2

Essayez de lire les fichiers correspondants à partir du fichier ab.py et ainsi de suite.

ab.py


import a
import b


print('ab file')

bc.py


import b
import c

print('bc file')

ca.py


import c
import a

print('ca file')

abc_main.py


import ab
import bc
import ca

print('abc main file')

abc_main.py

Lorsque j'exécute abc_main.py, cela ressemble à ceci:

a file
b file
ab file
c file
bc file
ca file
abc main file

Il semble que les fichiers a et b soient lus en premier. Après cela, puisque les fichiers b et c sont lus, il doit être sorti en tant que fichier b, mais il est ignoré et sorti en tant que fichier c.

Apparemment, il ne se charge pas une fois qu'il est chargé.

La lecture du fichier ca ne semble pas être fâchée car les fichiers c et a ont déjà été lus. Sauf le fait qu'une fois qu'un «fichier», etc. est lu, il n'est pas lu après cela et n'est sorti qu'une seule fois.

Apparemment, le fichier est essentiellement lu une seule fois. ''

Essayez d'utiliser le module un niveau ci-dessous

Actuellement, j'utilisais des modules sous le même répertoire tels que abc_main et calc_main.

Ensuite, est-il possible d'utiliser un module dans le répertoire inférieur suivant comme main.py?

main.py

main.py


from calc import add

'''
add.py
calc.add
5
'''
print(add.add(2, 3))

Comme mentionné ci-dessus, le module add est importé du répertoire calc. C'est le code qui fonctionne réellement.

En d'autres termes, depuis Python 3.3, vous pouvez utiliser les modules sous le répertoire. Aussi, si vous vous concentrez sur nom

calc.add

Est sortie. Par conséquent, il semble qu'il soit chargé en tant que module d'ajout de l'espace calc. Cela semble être une fonctionnalité appelée «importation d'espace de noms» depuis Python 3.3.

Cependant, cela ne fonctionne pas bien si vous procédez comme suit.

main.py



'''
    from calc import add.add
                        ^
SyntaxError: invalid syntax
'''
from calc import add.add
print(add(2, 3))



'''
AttributeError: module 'calc' has no attribute 'add'
'''
import calc
print(calc.add.add(2, 3))

Apparemment, il semble qu'il ne soit pas permis de ** affiner davantage ** en utilisant "." Dans le contenu écrit après l'importation.

De plus, il semble que ** la lecture du répertoire en tant que module ** ne soit pas autorisée.

paquet

Qu'est-ce qu'un package?

Un package est un "** module ** qui gère tous les modules". Par exemple, j'ai créé le répertoire calc plus tôt.

.
├── calc
│   ├── __pycache__
│   │   ├── add.cpython-37.pyc
│   │   ├── mul.cpython-37.pyc
│   │   └── sub.cpython-37.pyc
│   ├── add.py
│   ├── calc_main.py
│   ├── mul.py
│   └── sub.py

En mettant ** __ init __. Py ** dans ce répertoire calc, Vous pouvez considérer le répertoire calc lui-même comme un ** grand module **.

Bien sûr, sans __init __. Py, le répertoire calc n'est qu'un" répertoire ". Par conséquent, en mettant «__init __. Py», le répertoire calc lui-même est considéré comme un ** module **.

En utilisant des packages, vous pouvez gérer les fichiers dans des unités plus grandes et les structurer.

Qu'en est-il de «__init __. Py»?

__init __. py est la première chose à exécuter lorsque vous appelez ce module de package.

__init__.py


print(__name__)

Si vous le faites, le nom du répertoire sera affiché.

C'est parce que le répertoire est traité comme un "module" par «__init __. Py».

Essayez de réécrire calc

Essayez de réécrire le répertoire calc du package.

calc_main.py


print(__name__)

from . import add
from . import sub
from . import mul

print(add.add(2, 3))

Je vais essayer.

Pour le moment, l'exécution normale de python ne fonctionne pas.

python calc/calc_main.py
python calc_main.py

Etc

  File "calc_main.py", line 3, in <module>
    from . import add
ImportError: cannot import name 'add'

Erreur se produit.

python -m calc.calc_main.py

Puis

Vous pouvez exécuter calc_main.py avec calc en tant que package.

Comme vous pouvez le voir, le paquet est essentiellement un "chemin relatif" et semble maintenant être spécifié.

python calc/calc_main.py
python calc_main.py

C'est la raison pour laquelle ça ne marche pas Réécrivez avec le code suivant.

print(__name__)
print(__package__)

from . import add
from . import sub
from . import mul

print(add.add(2, 3))
python -m calc.calc_main.py

calc
__main__
calc
add.py
calc.add
sub.py
calc.sub
mul.py
calc.mul
5

python calc/calc_main.py

__main__
None
Traceback (most recent call last):
  File "calc/calc_main.py", line 4, in <module>
    from . import add
ImportError: cannot import name 'add'

Ce sera.

Ici, comme la différence entre eux À quel paquet appartient package? Représente (module parent) Sur celui qui ne fonctionne pas, l'attribut package est None. Par conséquent, je ne sais pas à quel package faire référence et j'obtiens une erreur. En d'autres termes, même si vous spécifiez "." Etc., ce sera "Chemin relatif à partir de quel paquet?".

pour cette raison, Si vous utilisez le package calc du répertoire principal

main.py



from calc import calc_main

print(10)
calc
calc.calc_main
calc
add.py
calc.add
sub.py
calc.sub
mul.py
calc.mul
5
10

Il sera exécuté correctement.

Par conséquent, il semble que cela fonctionne bien dans la situation où l'attribut __package__ est spécifié correctement et dans le cas d'une importation relative.

Site de référence [[Python] Importer une pierre d'achoppement](https://qiita.com/ysk24ok/items/2711295d83218c699276#package ne peut pas utiliser implicit-relative-import) J'ai essayé de résumer les modules Python Idée sur Python: différences entre les packages et les modules Python

Je vais spécifier correctement le package du module avec l'option -m.

Dans PyCharm?

Que dois-je faire lorsque j'utilise PyCharm? Apparemment, PyCharm se comporte différemment de Python normal. IDE semble faire une bonne supposition et se comporter différemment.

1. Utilisez le chemin relatif lors du chargement des modules

Les chemins relatifs sont utilisés lors du chargement de modules dans un package.

Dans le même package, un chemin relatif est utilisé.

calc_main.py


print(__name__)
print(__package__)

from . import add

print(add.add(2, 3))

2. Lorsque vous utilisez le package, écrivez comme d'habitude

Lorsque vous frappez le paquet d'en haut, vous pouvez le laisser tel quel. Appelez-le comme un module normal.

main.py


from calc import calc_main

print(10)

3. Le fichier ne peut pas être lu dans le package, alors faites-le à partir de la commande

Dans PyCharm, il y a des choses comme l'exécution de la configuration de démarrage, Lorsque vous essayez d'exécuter un fichier dans un package

calc_main.py


print(__name__)
print(__package__)

from . import add

print(add.add(2, 3))

Aucun n'est généré avec package et une erreur se produit car le package n'est pas évalué. Dans ce cas

Depuis la ligne de commande

python -m calc.calc_main

Vous pouvez le donner comme.

L'exécution de la configuration de lancement de PyCharm ne fonctionne pas. C'est ennuyeux qu'il soit difficile de tester l'exécution d'un seul fichier ... Y a-t-il un moyen de bien le faire ...

https://pleiades.io/help/pycharm/content-root.html

Recommended Posts

Apprenez à connaître les packages et les modules Python
Cours de base Python (14 modules et packages)
Organisez les modules et les packages Python dans le désordre
Obtenez une compréhension abstraite des modules et des packages Python
Paquets qui gèrent le MIDI avec Python midi et pretty_midi
[Python / matplotlib] Comprendre et utiliser FuncAnimation
A propos des modules Python Primer et des expressions conditionnelles
Environnement virtuel Python et packages sur Ubuntu
[Python] Empaquetez et distribuez vos propres modules
Comprenez les listes Python, les dictionnaires, etc.
[python] Compresser et décompresser
Liste des modules python
Astuces Python et Numpy
[Python] pip et roue
Itérateur et générateur Python
Ruby, Python et carte
entrée et sortie python
Utilisation des packages Python #external
Python et Ruby se séparent
Python asyncio et ContextVar
Python - Explication et résumé de l'utilisation des 24 meilleurs packages
Comprenez attentivement la distribution exponentielle et dessinez en Python
Tracer et comprendre la distribution normale multivariée en Python
Comprendre attentivement la distribution de Poisson et dessiner en Python
Gérez les packages d'exécution Python et les packages d'environnement de développement avec Poetry
Programmation avec Python et Tkinter
Chiffrement et déchiffrement avec Python
Comprendre t-SNE et améliorer la visualisation
Python: variables de classe et d'instance
3-3, chaîne Python et code de caractère
Série Python 2 et série 3 (édition Anaconda)
Python et matériel - Utilisation de RS232C avec Python -
Python sur Ruby et Ruby en colère sur Python
Comprendre le DataSet et le DataLoader de PyTorch (2)
Indentation Python et format de chaîne
[Python] Chargement de modules personnalisés à plusieurs niveaux
division des nombres réels python (/) et division des nombres entiers (//)
Installez Python et Flask (Windows 10)
Comprendre le DataSet et le DataLoader de PyTorch (1)
À propos des objets et des classes Python
Liste des informations sur les arguments de méthode pour les classes et les modules en Python
À propos des variables et des objets Python
Essayez de comprendre Python soi
Apache mod_auth_tkt et Python AuthTkt
Å (Ongustorome) et NFC @ Python
# 2 [python3] Séparation et commentaire
Copie superficielle Python et copie profonde
Mémo tranche python et rubis
Installation de Python et grammaire de base
J'ai comparé Java et Python!
Copie superficielle Python et copie profonde
À propos de Python, len () et randint ()
Un moyen standard de développer et de distribuer des packages en Python
À propos de la date et du fuseau horaire Python
Installez Python 3.7 et Django 3.0 (CentOS)
Construction d'environnement Python et TensorFlow
Variables de classe et d'instance Python
Feuille de route pour la publication de packages Python