Maison  >  Article  >  développement back-end  >  Importer des notes d'étude en python

Importer des notes d'étude en python

高洛峰
高洛峰original
2017-02-03 16:05:201528parcourir

Avant-propos

Il existe deux façons d'organiser les modules en python, l'une est un simple fichier python, le nom du fichier est le nom du module, l'autre est un package, un package est un répertoire contenant plusieurs fichiers python . Il doit y avoir un fichier __init__.py dans le répertoire, donc le nom du répertoire est le nom du module. Les fichiers python du package peuvent également être importés via la syntaxe nom du package.file name import

import. 🎜>

Il existe deux types de syntaxe d'importation

1 Importer directement des modules

import Module
import Module as xx

2. , classes, fonctions, variables, etc.)

from Module import Name
from Module immport Name as yy

car la syntaxe est utilisée pour définir l'alias d'un objet (l'objet fait ici référence aux modules, classes, fonctions, etc.) , et import introduit le nom de l'objet dans l'espace de noms du fichier actuel

Supposons qu'il existe la structure de répertoires suivante

├── A.py
└── pkg
 ├── B.py
 └── __init__.py

Dans le répertoire actuel, le suivant les déclarations sont valides

import A
import pkg
import pkg.B
from pkg import B

Afin de simplifier la discussion, il n'y aura pas d'exemples de syntaxe ci-dessous

étapes d'importation


Toutes les informations du module chargé en python sont stockées dans la structure sys.modules Lors de l'importation d'un module, procédera comme suit

S'il s'agit de l'importation A, vérifiez s'il y a déjà A dans sys.modules, s'il y en a. c'est-à-dire qu'il ne sera pas chargé, sinon, créez un objet module pour A, et chargez A

S'il provient de A, importez B, créez d'abord un objet module pour A, puis analysez A, recherchez B à partir de et remplissez-le dans le __dict__


Importation imbriquée


Lors de l'importation d'un module, nous pouvons nous demander si un module sera importé plusieurs fois. Supposons qu'il y ait trois modules. A, B et C. A doit importer B et C, et B doit importer C. De cette façon, A exécutera Import C deux fois, une fois par lui-même et une fois par lui-même lors de l'importation de B. Cependant, selon le étapes d'importation mentionnées ci-dessus, il a été constaté que le module a été chargé lors de la deuxième importation, donc l'importation ne sera pas répétée

Mais une erreur sera signalée dans la situation suivante

#filename: A.py
from B import BB
class AA:pass
 
#filename: B.py
from A import AA
class BB:pass

À ce moment-là, que A.py ou B.py soit exécuté, une exception ImportError sera levée. Supposons que nous exécutons A. py, la raison est la suivante

Quand. le fichier A.py s'exécute à partir de B import BB, B.py sera analysé en premier et un objet module sera créé pour B dans l'espace de noms de A, en essayant de trouver BB à partir de B

Scannez la première ligne de B.py et exécuté à partir de A import AA À ce moment, il analysera A.py

Scanner la première ligne de A.py et exécuter à partir de B import BB Puisque l'étape 1 est déjà B crée un. objet module, il obtiendra donc BB directement à partir du __dict__ de l'objet module de B. Évidemment, BB ne peut pas être obtenu pour le moment, donc une exception est levée


Il existe deux façons de résoudre cette situation. Dans un sens,

passez de B import BB à import B, ou passez de A import AA à import A

Échangez les deux lignes de code dans A.py ou B.py


En bref, ce à quoi vous devez faire attention lors de l'importation, c'est d'essayer d'importer

package import


quand il y a __init__ dans un répertoire. fichier, le répertoire est un package python

L'importation d'un package revient à importer un seul fichier. Nous pouvons faire une analogie comme celle-ci :

Lors de l'importation d'un seul fichier, les classes et les fonctions. dans le fichier, les variables peuvent être utilisées comme objets d'importation

Lors de l'importation d'un package, les sous-packages, les fichiers du package, ainsi que les classes, fonctions et variables dans __init__.py peuvent être utilisés comme objets d'importation

Supposons qu'il existe la structure de répertoires suivante

pkg
├── __init__.py
└── file.py

Le contenu de __init__.py est le suivant

argument = 0
class A:pass

Exécuté dans le même répertoire que pkg Les déclarations suivantes sont OK

>>> import pkg
>>> import pkg.file
>>> from pkg import file
>>> from pkg import A
>>> from pkg import argument

mais les déclarations suivantes sont fausses

>>> import pkg.A
>>> import pkg.argument

ImportError : Aucun module nommé xxx, car lorsque nous exécutons l'import A.B, A et B doivent être des modules (fichiers ou packages)

Import relatif et import absolu


Le format de l'absolu import est import A.B ou from A import B, le format d'importation relatif est from .import B ou from ..A import B, .. représente le module de niveau supérieur, ... représente le niveau supérieur. module, et ainsi de suite. Lorsque nous avons plusieurs packages, il peut être nécessaire d'importer le contenu d'un package dans un autre, ce qui entraînera une importation absolue, et c'est souvent à ce moment-là que des erreurs sont les plus susceptibles de se produire. Permettez-moi d'illustrer avec un exemple spécifique

La structure des répertoires est la suivante

app
├── __inti__.py
├── mod1
│ ├── file1.py
│ └── __init__.py
├── mod2
│ ├── file2.py
│ └── __init__.py
└── start.py

Le contenu de app/start.py est import mod1.file1


app/mod1 /file1.py content Pour from ..mod2 import file2

Afin de faciliter l'analyse, nous ajoutons print __file__, __name__

à la première ligne de tous les fichiers py (y compris __init__.py) maintenant app/mod1/file1. L'importation relative est utilisée dans py. Lorsque nous exécutons python file1.py sous app/mod1 ou exécutons python mod1/file1.py sous app, l'erreur ValueError : tentative d'importation relative dans un non-package

.

sera signalé lors de l'exécution sous app. python -m mod1.file1 ou python start.py signalera une erreur ValueError : tentative d'importation relative au-delà du package de niveau supérieur

Les raisons spécifiques seront discutées plus tard. regardez quelques règles lors de l'importation de modules

Lorsque la structure du package n'est pas explicitement spécifiée, python détermine la structure d'un module dans le package en fonction de __name__ S'il s'agit de __main__, c'est le module de niveau supérieur lui-même et. n'a pas de structure de package. S'il s'agit de la structure A.B.C, alors le module de niveau supérieur est A.

Suivez essentiellement ce principe

S'il s'agit d'une importation absolue, un module ne peut importer que ses propres sous-modules ou modules et sous-modules au même niveau que son module de niveau supérieur

S'il s'agit d'une importation relative, un module doit avoir une structure de package et ne peut importer des modules qu'à l'intérieur de son module de niveau supérieur


La structure des répertoires est la suivante

A
├── B1
│ ├── C1
│ │ └── file.py
│ └── C2
└── B2

其中A,B1,B2,C1,C2都为包,这里为了展示简单没有列出__init__.py文件,当file.py的包结构为A.B1.C1.file(注意,是根据__name__来的,而不是磁盘的目录结构,在不同目录下执行file.py时对应的包目录结构都是不一样的)时,在file.py中可采用如下的绝对的导入

import A.B1.C2
import A.B2

和如下的相对导入

from .. import C2
from ... import B2

什么情况下会让file.py的包结构为A.B1.C1.file呢,有如下两种

在A的上层目录执行python -m A.B1.C1.file, 此时明确指定了包结构

在A的上层目录建立文件start.py,在start.py里有import A.B1.C1.file,然后执行python start.py,此时包结构是根据file.py的__name__变量来的

再看前面出错的两种情况,第一种执行python file1.py和python mod1/file1.py,此时file.py的__name__为__main__ ,也就是说它本身就是顶层模块,并没有包结构,所以会报错

第二种情况,在执行python -m mod1.file1和python start.py时,前者明确告诉解释器mod1是顶层模块,后者需要导入file1,而file1.py的__name__为mod1.file1,顶层模块为也mod1,所以在file1.py中执行from ..mod2 import file2时会报错 ,因为mod2并不在顶层模块mod1内部。通过错误堆栈可以看出,并不是在start.py中绝对导入时报错,而是在file1.py中相对导入报的错

那么如何才能偶正确执行呢,有两种方法,一种是在app上层目录执行python -m app.mod1.file1,另一种是改变目录结构,将所有包放在一个大包中,如下

   
app
├── pkg
│ ├── __init__.py
│ ├── mod1
│ │ ├── __init__.py
│ │ └── file1.py
│ └── mod2
│ ├── __init__.py
│ └── file2.py
└── start.py

start.py内容改成import pkg.mod1.file1,然后在app下执行python start.py

总结

以上就是这篇文章的全部内容了,希望本文的内容对大家学习或者使用python能带来一定的帮助,如有疑问大家可以留言交流。

更多python中import学习备忘笔记相关文章请关注PHP中文网!

Déclaration:
Le contenu de cet article est volontairement contribué par les internautes et les droits d'auteur appartiennent à l'auteur original. Ce site n'assume aucune responsabilité légale correspondante. Si vous trouvez un contenu suspecté de plagiat ou de contrefaçon, veuillez contacter admin@php.cn