Wenn Sie Python berühren, können Sie den Unterschied zwischen einem Modul und einem Paket nicht wirklich erkennen. Besonders wenn eine IDE namens PyCharm verwendet wird, verhält sie sich seltsam.
Daher möchte ich den Kampf zwischen dem Paket und dem Modul zusammenfassen, damit ich später darauf zurückblicken kann.
Berühren wir zuerst das Modul.
Module repräsentieren "Dateien" in Python. Mit anderen Worten, wenn Sie eine Datei mit dem Namen "add.py" erstellen, handelt es sich um ein Modul mit dem Namen "add".
Durch die Trennung der Funktionen für jedes Modul kann vermieden werden, dass die Funktionen in eine einzelne Datei umgewandelt werden.
Derzeit verwenden wir eine solche Verzeichnisstruktur.
In einem Verzeichnis namens Python_Tutorial Enthält Folgendes:
.
├── __pycache__
├── calc
│ ├── add.py
│ ├── calc_main.py
│ ├── mul.py
│ └── sub.py
└── main.py
Schreiben Sie das Modul in das Verzeichnis calc Versuchen Sie dann, ein anderes Rechenmodul von calc_main aus aufzurufen. Versuchen Sie danach, main.py direkt unter Python_Tutorial zu verwenden.
add.py, mul.py, sub.py Bereiten.
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))
mit add.py etc.
if __name__ == '__main__':
print(mul(10, 20))
Ist beigefügt, aber was ist das?
Es enthält den "Namen, als die Datei $ f $ .py ausgeführt wurde".
Versuchen Sie beispielsweise, add.py auszuführen. dann,
add.py
__main__
30
Wird ausgegeben.
Dies liegt daran, dass es ausgehend von der Datei $ f $ = add ausgeführt wird und main in name der ausführbaren Datei festgelegt ist.
Beachten Sie, dass name in der Ausführungsursprungsdatei immer main ist.
Versuchen Sie, add, sub, mul im selben Verzeichnis wie calc_main.py auszuführen.
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))
Anscheinend
Importieren Sie den Dateinamen in dieselbe Hierarchie
Es scheint also, dass andere Dateien als Module gelesen werden können.
import add
Wenn Sie dies tun, werden zwei Ausdrucke von add.py ausgeführt. Daher scheint es, dass eine solide Schreibverarbeitung wie Drucken ausgeführt wird, wenn das Modul geladen wird. Außerdem enthält name add. Auf diese Weise scheint der Dateiname so eingegeben zu werden, wie er ist, wenn er als Modul anstelle des Ausführungsstartpunkts aufgerufen wird.
Dateiname importieren Da es eingelesen ist, kann die Funktion in add.add verwendet werden, dem Namespace des Dateinamens.
Diese Notation scheint sicher zu sein, da die Funktion "Hinzufügen" die Namespaces des anderen schützt, selbst wenn sie sich in anderen Dateien befinden!
from sub import sub
Wenn Sie dies tun, scheinen Sie die Unterfunktion von sub.py direkt zu lesen. Es scheint möglich zu sein, es aus dem Modul zu entfernen.
Es scheint jedoch, dass die Unterfunktion nicht direkt abgerufen werden kann. Wie add.py
'''
sub.py
sub
'''
Wird ausgegeben, so scheint es, dass der gesamte Inhalt der Subdatei zum Zeitpunkt von from sub ausgeführt wird.
from mul import *
Sie können den gesamten Inhalt der Mul-Datei in großen Mengen in den Namespace calc_main.py erzwingen.
Grundsätzlich ** scheint es besser, nicht zu verwenden **. Der Grund dafür ist, dass es zu unerwartetem Verhalten kommt, z. B. zum Überschreiben, wenn derselbe Name wie bei anderen Modulen verwendet wird.
Dateiname importieren
Kann am bequemsten sein.
Versuchen Sie als nächstes das mehrfache Laden. Ich bin ein Baum, wie es sich verhält, wenn dieselbe Datei oft gelesen wird
Um zu versuchen, mehrere zu laden a b Eine einfache Konfiguration wie c scheint einfacher zu sein.
Versuche Folgendes.
.
├── __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
Abc-Verzeichnis hinzugefügt. ab.py liest a- und b-Dateien als Module.
print('a file')
aa = 1
print('b file')
bb = 2
print('c file')
cc = 3
Das Experiment beginnt mit a, b und c.py wie oben beschrieben.
Versuchen Sie, die entsprechenden Dateien aus der Datei ab.py usw. zu lesen.
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
Wenn ich abc_main.py starte, sieht es so aus:
a file
b file
ab file
c file
bc file
ca file
abc main file
Es scheint, dass die Dateien a und b zuerst gelesen werden. Danach sollten B- und C-Dateien als B-Datei ausgegeben, aber übersprungen und als C-Datei ausgegeben werden.
Anscheinend wird es nicht geladen, sobald es geladen ist.
Das Lesen der ca-Datei scheint nicht zu ärgern, da die c- und a-Dateien bereits gelesen wurden. Mit Ausnahme der Tatsache, dass "eine Datei" usw., wenn sie einmal gelesen wird, danach nicht mehr gelesen und nur einmal ausgegeben wird.
Anscheinend wird die Datei grundsätzlich nur einmal gelesen. ``
Derzeit habe ich Module im selben Verzeichnis wie abc_main und calc_main verwendet.
Ist es dann möglich, ein Modul im nächstniedrigeren Verzeichnis wie main.py zu verwenden?
main.py
main.py
from calc import add
'''
add.py
calc.add
5
'''
print(add.add(2, 3))
Wie oben erwähnt, wird das Add-Modul aus dem Calc-Verzeichnis importiert. Dies ist der Code, der tatsächlich funktioniert.
Mit anderen Worten, seit Python 3.3 können Sie die Module unter dem Verzeichnis verwenden. Wenn Sie sich auf name konzentrieren
calc.add
Wird ausgegeben. Daher scheint es als Add-Modul des Calc-Space geladen zu sein. Dies scheint eine Funktion zu sein, die seit Python 3.3 als "Namespace-Import" bezeichnet wird.
Es funktioniert jedoch nicht gut, wenn Sie Folgendes tun.
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))
Anscheinend scheint es nicht erlaubt zu sein, mit "." In den nach dem Import geschriebenen Inhalten weiter einzugrenzen.
Es scheint auch, dass ** das Lesen des Verzeichnisses als Modul ** nicht erlaubt ist.
Ein Paket ist ein "** Modul **, das alle Module verwaltet". Zum Beispiel habe ich das calc-Verzeichnis früher erstellt.
.
├── calc
│ ├── __pycache__
│ │ ├── add.cpython-37.pyc
│ │ ├── mul.cpython-37.pyc
│ │ └── sub.cpython-37.pyc
│ ├── add.py
│ ├── calc_main.py
│ ├── mul.py
│ └── sub.py
Indem Sie ** __ init __. Py
** in dieses Calc-Verzeichnis einfügen,
Sie können sich das Calc-Verzeichnis selbst als ein ** großes Modul ** vorstellen.
Ohne "__init __. Py" ist das calc-Verzeichnis natürlich nur ein "Verzeichnis". Wenn Sie "__init __. Py" eingeben, wird das Calc-Verzeichnis selbst als ** Modul ** betrachtet.
Mithilfe von Paketen können Sie Dateien in größeren Einheiten verarbeiten und strukturieren.
__init __. Py
?__init __. py
ist das erste, was ausgeführt wird, wenn Sie dieses Paketmodul aufrufen.
__init__.py
print(__name__)
In diesem Fall wird der Verzeichnisname ausgegeben.
Dies liegt daran, dass das Verzeichnis von "__init __. Py" als "Modul" behandelt wird.
Versuchen Sie, das Calc-Verzeichnis für das Paket neu zu schreiben.
calc_main.py
print(__name__)
from . import add
from . import sub
from . import mul
print(add.add(2, 3))
Ich werde versuchen.
Zu diesem Zeitpunkt funktioniert die normale Python-Ausführung nicht.
python calc/calc_main.py
python calc_main.py
Und so weiter
File "calc_main.py", line 3, in <module>
from . import add
ImportError: cannot import name 'add'
Fehler tritt auf.
python -m calc.calc_main.py
Dann
Sie können calc_main.py mit calc als Paket ausführen.
Wie Sie sehen können, ist das Paket im Grunde ein "relativer Pfad" und scheint nun angegeben zu sein.
python calc/calc_main.py
python calc_main.py
Das ist der Grund, warum es nicht funktioniert Schreiben Sie mit dem folgenden Code neu.
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'
Es wird sein.
Hier als Unterschied zwischen ihnen Zu welchem Paket gehört package? Repräsentiert (übergeordnetes Modul) Bei demjenigen, der nicht funktioniert, lautet das Attribut package None. Daher weiß ich nicht, auf welches Paket ich mich beziehen soll, und es wird eine Fehlermeldung angezeigt. Mit anderen Worten, selbst wenn Sie "." Usw. angeben, ist dies "Relativer Pfad von welchem Paket?".
aus diesem Grund, Wenn Sie das Calc-Paket aus dem Hauptverzeichnis verwenden
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
Es wird ordnungsgemäß ausgeführt.
Daher scheint es in der Situation gut zu funktionieren, in der das Attribut __package__
richtig angegeben ist, und im Fall eines relativen Imports.
Referenzseite [[Python] Stolperstein importieren](https://qiita.com/ysk24ok/items/2711295d83218c699276#package kann den impliziten relativen Import nicht verwenden) Ich habe versucht, die Python-Module zusammenzufassen Idee zu Python: Unterschiede zwischen Python-Paketen und -Modulen
Ich werde das Modulpaket mit der Option -m richtig angeben.
Was soll ich tun, wenn ich PyCharm verwende? Anscheinend verhält sich PyCharm anders als normales Python. IDE scheint eine gute Vermutung anzustellen und sich anders zu verhalten.
Relative Pfade werden beim Laden von Modulen innerhalb eines Pakets verwendet.
Im selben Paket wird der relative Pfad verwendet.
calc_main.py
print(__name__)
print(__package__)
from . import add
print(add.add(2, 3))
Wenn Sie das Paket von oben treffen, können Sie es so lassen, wie es ist. Nennen Sie es wie ein normales Modul.
main.py
from calc import calc_main
print(10)
In PyCharm gibt es eine Startkonfigurationsausführung usw. Beim Versuch, eine Datei in einem Paket auszuführen
calc_main.py
print(__name__)
print(__package__)
from . import add
print(add.add(2, 3))
Mit package wird keine ausgegeben, und es tritt ein Fehler auf, weil das Paket nicht beurteilt wird. In einem solchen Fall
Über die Befehlszeile
python -m calc.calc_main
Sie können es als geben.
Das Ausführen der PyCharm-Startkonfiguration funktioniert nicht. Es ist ärgerlich, dass es schwierig ist, die Ausführung einer einzelnen Datei zu testen ... Gibt es eine Möglichkeit, es gut zu machen ...
https://pleiades.io/help/pycharm/content-root.html
Recommended Posts