[Python] La pierre d'achoppement de l'importation

Une note personnelle sur les importations Python. Si vous avez des erreurs ou d'autres obstacles, veuillez commenter et PR.

L'importation relative implicite ne peut pas être utilisée pour l'importation dans le package

L'histoire après Python3.

Par exemple

$ tree .
.
└── mypackage
    ├── __init__.py
    ├── mymodule1.py
    └── mymodule2.py

Je souhaite importer mymodule1.py depuis mymodule2.py lorsque la structure de répertoire est.

python:./mypackage/mymodule1.py


A = 1000

def show():
    print('A: {}'.format(A))

python:./mypackage/mymodule2.py


import mymodule1

B = 100

def show():
    print('A: {}, B: {}'.format(mymodule1.A, B))

Quand,

$ python2.7
Python 2.7.10 (default, Oct 23 2015, 19:19:21)
[GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import mypackage.mymodule2 as mymod2
>>> mymod2.show()
A: 1000, B: 100
$ python3
Python 3.5.2 (default, Aug  4 2016, 09:38:15)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import mypackage.mymodule2 as mymod2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/Users/yusuke-nishioka/tests/tests1/mypackage/mymodule2.py", line 3, in <module>
    import mymodule1
ImportError: No module named 'mymodule1'

Comme, dans Python 2.7, mymodule1.py peut être importé depuis mymodule2.py, Vous pouvez voir qu'il ne peut pas être importé dans Python 3.5.

Cause

ʻImport mymodule1dans mymodule2.py Il est prévu d'importer mymodule1.py dans la même hiérarchie (c'est ce qu'on appelle l'importation relative implicite). Cependant, s'il y a un paquet avec le même nom danssys.path`, Essayez-vous d'importer mypackage / mymodule1.py? Essayez-vous d'importer un package appelé mymodule sur sys.path? Il y a un problème qui ne peut être distingué.

Par conséquent, dans la série Python3, ʻimport xxx est modifié pour importer le paquet existant dans sys.path` (appelé importation absolue). L'importation relative implicite n'est plus possible.

Solution

Pour importer les modules dans le package Il doit être clairement indiqué qu'il s'agit d'une importation relative, telle que «from .import mymodule1» (c'est ce qu'on appelle une importation relative explicite).

URL de référence

https://www.python.org/dev/peps/pep-0328/#rationale-for-relative-imports

Lorsque l'attribut «package» est Aucun et que l'attribut «name» est «main», l'importation relative ne peut pas être utilisée.

Eh bien, j'ai mentionné ci-dessus que j'utilise une importation relavtive explicite pour importer les modules dans le package, Il y a des cas où l'importation relative ne peut pas être utilisée même si le module est dans le package. C'est à ce moment que l'attribut «package» du module dans le paquet est «None» et que l'attribut «name» est «main».

$ tree .
.
└── mypackage
    ├── __init__.py
    ├── main.py
    └── mymodule.py

mypackge/mymodule.py


A = 1000

def show():
    print('A: {}'.format(A))

mypackage/main.py


from . import mymodule

if __name__ == '__main__':
    print('__package__: {}, __name__: {}'.format(
        __package__, __name__))
    mymodule.show()

Lorsque vous exécutez main.py

$ python3 mypackage/main.py
Traceback (most recent call last):
  File "mypackage/main.py", line 1, in <module>
    from . import mymodule
ImportError: cannot import name 'mymodule'

S'affiche et vous pouvez voir que mypackage / mymodule.py n'a pas pu être importé.

Cause

À ce stade, l'attribut __package de main.py est None et l'attribut __name__ est __main__. Il est reconnu comme un module de premier niveau. Par conséquent, . of from . devient main.py lui-même et mymodule ne peut pas être importé.

Solution 1

Soit from .import mymodule être from mymodule import show.

Solution 2

Exécutez avec l'option -m.

$ python3 -m mypackage.main
__package__: mypackage, __name__: __main__
A: 1000

L'attribut «__package» est «mypackage» et l'attribut «name» est «main». . Of from . pointera vers la même hiérarchie que main.py, Vous pouvez importer mymodule.py avec from .import mymodule.

En passant, l'exécution de main.py par -m doit être faite de l'extérieur du paquet.

$ cd mypackage
$ python3 -m main
Traceback (most recent call last):
  File "/Users/yusuke-nishioka/.anyenv/envs/pyenv/versions/3.6.1/lib/python3.6/runpy.py", line 193, in _run_module_as_main
    "__main__", mod_spec)
  File "/Users/yusuke-nishioka/.anyenv/envs/pyenv/versions/3.6.1/lib/python3.6/runpy.py", line 85, in _run_code
    exec(code, run_globals)
  File "/Users/yusuke-nishioka/Documents/United/tmp/mypackage/main.py", line 1, in <module>
    from . import mymodule
ImportError: attempted relative import with no known parent package

URL de référence

https://www.python.org/dev/peps/pep-0328/#relative-imports-and-name

Vous pouvez importer des packages sans __init __. Py

L'histoire de Python 3.3 ou version ultérieure.

$ tree
.
├── mypackage1
│   ├── __init__.py
│   └── subdir1
│       ├── __init__.py.bak
│       └── mymodule1.py
└── mypackage2
    └── subdir1
        └── mymodule2.py

Quand,

$ python3
Python 3.5.2 (default, Aug  4 2016, 09:38:15)
[GCC 4.2.1 Compatible Apple LLVM 7.3.0 (clang-703.0.31)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import mypackage1
>>> import mypackage2
>>> dir(mypackage1)
['__builtins__', '__cached__', '__doc__', '__file__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
>>> dir(mypackage2)
['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']

Comme, vous pouvez importer sans __init __. Py. Paquet régulier, mypackage1 avec __init __. Py Mypackage2 sans__init __. Py est appelé un package d'espace de noms.

plus loin,

>>> import sys
>>> sys.path.append('./mypackage1')
>>> sys.path.append('./mypackage2')
>>> import subdir1
>>> dir(subdir1)
['__doc__', '__loader__', '__name__', '__package__', '__path__', '__spec__']
>>> subdir1.__path__
_NamespacePath(['./mypackage1/subdir1', './mypackage2/subdir1'])

En tant que package qui appartient au même espace de noms même si le répertoire a un chemin différent mais le même nom Stocké dans l'objet _NamespacePath.

Commande d'importation

Lorsque ʻimport xxx` est exécuté,

Différence entre le package standard et le package d'espace de noms

La différence est

etc.

De plus, en en faisant un package d'espace de noms (en éliminant __init __. Py)

>>> import subdir1.mymodule1
>>> import subdir1.mymodule2
>>> subdir1.mymodule1.__file__
'./mypackage1/subdir1/mymodule1.py'
>>> subdir1.mymodule2.__file__
'./mypackage2/subdir1/mymodule2.py'

Avec mymodule1.py under. / Mypackage1 / subdir1, comme Il peut être importé séparément de mymodule2.py sous. / Mypackage2 / subdir1.

Résumé

Je ne peux pas penser à une scène où j'utilise intentionnellement le package d'espace de noms, Même si vous oubliez par inadvertance __init __. Py, vous pouvez l'importer en tant que module. Cependant, considérant que le processus d'initialisation peut être exécuté au moment de l'importation (comme par exemple en définissant __all__), Sauf si vous avez une raison spécifique, il semble préférable de mettre __init __. Py.

Voir PEP 420 - Packages d'espaces de noms implicites pour plus d'informations.

URL de référence

PEP 420 -- Implicit Namespace Packages 2012/07/24 J'ai essayé le package d'espace de noms Python 3.3b1

Recommended Posts

[Python] La pierre d'achoppement de l'importation
le zen de Python
Vers la retraite de Python2
À propos des fonctionnalités de Python
Le pouvoir des pandas: Python
L'histoire de Python et l'histoire de NaN
First Python 3 ~ Le début de la répétition ~
Différent du type d'importation de python. Signification de depuis A import B
Existence du point de vue de Python
pyenv-changer la version python de virtualenv
[Note] Importation de fichiers dans le répertoire parent en Python
[Python] Comprendre le potentiel_field_planning de Python Robotics
Revue des bases de Python (FizzBuzz)
À propos de la liste de base des bases de Python
2015-11-26 python> Afficher la liste des fonctions du module> import math> dir (math)
Apprenez les bases de Python ① Débutants élémentaires
Changer la longueur des chaînes csv Python
Vérifiez le comportement du destroyer en Python
[Python3] Comprendre les bases de Beautiful Soup
Passez le chemin du module python importé
Notes d'apprentissage depuis le début de Python 1
Vérifier l'existence du fichier avec python
À propos de l'environnement virtuel de Python version 3.7
[Python3] Réécrire l'objet code de la fonction
Je ne connaissais pas les bases de Python
Le résultat de l'installation de python sur Anaconda
[Python] Essayez pydash de la version Python de lodash
[python] Vérifier la consommation de mémoire des variables
[Python] Importez le module d'un niveau supérieur
Vérifiez le chemin du module importé Python
L'histoire de la manipulation des variables globales Python
[python] [meta] Le type de python est-il un type?
Principes de base pour exécuter NoxPlayer en Python
Pandas du débutant, par le débutant, pour le débutant [Python]
Le modèle de projet Python auquel je pense.
À la recherche du FizzBuzz le plus rapide en Python
Cours de base Python (à la fin de 15)
Définissez le nom du processus du programme Python
[Python] Récupère le code de caractère du fichier
L'histoire du traitement A du blackjack (python)
Apprenez intuitivement la refonte de Python np
Note Python: le rôle secret de Kamma
Notes d'apprentissage depuis le début de Python 2
Traduction japonaise: PEP 20 - Le Zen de Python
[Python3] Comprendre les bases des opérations sur les fichiers
Importer le module Python
Importer un script python
Les bases de Python ①
Bases de python ①
Copie de python
Synthétiser l'importation Python
Introduction de Python
Récupérer le contenu de git diff depuis python
Sortie du nombre de cœurs de processeur en Python
[Python] Lire le code source de Bottle Part 2