Kontrolle von Symbolen und Kombination von Untermodulen

PythonPythonIntermediate
Jetzt üben

This tutorial is from open-source community. Access the source code

💡 Dieser Artikel wurde von AI-Assistenten übersetzt. Um die englische Version anzuzeigen, können Sie hier klicken

Einführung

In diesem Lab werden Sie wichtige Konzepte im Zusammenhang mit der Organisation von Python-Paketen lernen. Zunächst werden Sie erfahren, wie Sie die exportierten Symbole mithilfe von __all__ in Python-Modulen steuern können. Diese Fähigkeit ist von entscheidender Bedeutung für die Verwaltung dessen, was aus Ihren Modulen sichtbar gemacht wird.

Zweitens werden Sie verstehen, wie Sie Untermodule kombinieren können, um Importe zu vereinfachen, und die Technik des Modulaufteilens zur besseren Organisation Ihres Codes beherrschen. Diese Praktiken werden die Lesbarkeit und Wartbarkeit Ihres Python-Codes verbessern.

Dies ist ein Guided Lab, das schrittweise Anweisungen bietet, um Ihnen beim Lernen und Üben zu helfen. Befolgen Sie die Anweisungen sorgfältig, um jeden Schritt abzuschließen und praktische Erfahrungen zu sammeln. Historische Daten zeigen, dass dies ein Labor der Stufe Fortgeschrittener mit einer Abschlussquote von 62% ist. Es hat eine positive Bewertungsrate von 100% von den Lernenden erhalten.

Verständnis der Komplexität von Paket-Imports

Wenn Sie mit Python-Paketen beginnen, werden Sie schnell feststellen, dass das Importieren von Modulen recht kompliziert und umständlich werden kann. Diese Komplexität kann es schwieriger machen, Ihren Code zu lesen und zu schreiben. In diesem Lab werden wir uns dieser Frage genauer ansehen und lernen, wie wir den Importprozess vereinfachen können.

Aktuelle Importstruktur

Zunächst öffnen wir das Terminal. Das Terminal ist ein leistungsfähiges Werkzeug, das es Ihnen ermöglicht, mit dem Betriebssystem Ihres Computers zu interagieren. Sobald das Terminal geöffnet ist, müssen wir in das Projektverzeichnis wechseln. Das Projektverzeichnis ist der Ort, an dem alle Dateien unseres Python-Projekts gespeichert sind. Dazu verwenden wir den Befehl cd, der für "change directory" (Verzeichnis wechseln) steht.

cd ~/project

Jetzt, da wir uns im Projektverzeichnis befinden, lassen Sie uns die aktuelle Struktur des structly-Pakets untersuchen. Ein Paket in Python ist eine Möglichkeit, verwandte Module zu organisieren. Wir können den Befehl ls -la verwenden, um alle Dateien und Verzeichnisse innerhalb des structly-Pakets aufzulisten, einschließlich versteckter Dateien.

ls -la structly

Sie werden feststellen, dass es mehrere Python-Module innerhalb des structly-Pakets gibt. Diese Module enthalten Funktionen und Klassen, die wir in unserem Code verwenden können. Wenn wir jedoch die Funktionalität dieser Module nutzen möchten, müssen wir derzeit lange Importanweisungen verwenden. Beispielsweise:

from structly.structure import Structure
from structly.reader import read_csv_as_instances
from structly.tableformat import create_formatter, print_table

Diese langen Importpfade können mühsam zu schreiben sein, insbesondere wenn Sie sie mehrmals in Ihrem Code verwenden müssen. Sie machen Ihren Code auch weniger lesbar, was ein Problem sein kann, wenn Sie versuchen, Ihren Code zu verstehen oder zu debuggen. In diesem Lab werden wir lernen, wie wir das Paket so organisieren können, dass diese Imports einfacher werden.

Lassen Sie uns zunächst den Inhalt der __init__.py-Datei des Pakets betrachten. Die __init__.py-Datei ist eine besondere Datei in Python-Paketen. Sie wird ausgeführt, wenn das Paket importiert wird, und kann verwendet werden, um das Paket zu initialisieren und alle erforderlichen Imports einzurichten.

cat structly/__init__.py

Sie werden wahrscheinlich feststellen, dass die __init__.py-Datei entweder leer ist oder nur sehr wenig Code enthält. In den nächsten Schritten werden wir diese Datei ändern, um unsere Importanweisungen zu vereinfachen.

Das Ziel

Bis zum Ende dieses Labs möchten wir in der Lage sein, viel einfachere Importanweisungen zu verwenden. Anstelle der langen Importpfade, die wir zuvor gesehen haben, können wir Anweisungen wie diese verwenden:

from structly import Structure, read_csv_as_instances, create_formatter, print_table

Oder sogar:

from structly import *

Die Verwendung dieser einfacheren Importanweisungen wird unseren Code sauberer und einfacher zu bearbeiten machen. Es wird uns auch Zeit und Mühe sparen, wenn wir unseren Code schreiben und warten.

Steuerung exportierter Symbole mit __all__

In Python möchten Sie möglicherweise steuern, welche Symbole (Funktionen, Klassen, Variablen) aus einem Modul importiert werden, wenn Sie die Anweisung from module import * verwenden. Hier kommt die Variable __all__ zum Einsatz. Die Anweisung from module import * ist eine Möglichkeit, alle Symbole aus einem Modul in den aktuellen Namensraum zu importieren. Manchmal möchten Sie jedoch nicht jedes einzelne Symbol importieren, insbesondere wenn es viele gibt oder wenn einige für die interne Verwendung im Modul gedacht sind. Die Variable __all__ ermöglicht es Ihnen, genau anzugeben, welche Symbole bei Verwendung dieser Anweisung importiert werden sollen.

Was ist __all__?

Die Variable __all__ ist eine Liste von Strings. Jeder String in dieser Liste repräsentiert ein Symbol (Funktion, Klasse oder Variable), das ein Modul exportiert, wenn jemand die Anweisung from module import * verwendet. Wenn die Variable __all__ in einem Modul nicht definiert ist, wird die Anweisung import * alle Symbole importieren, die nicht mit einem Unterstrich beginnen. Symbole, die mit einem Unterstrich beginnen, werden normalerweise als privat oder intern für das Modul angesehen und sollen nicht direkt importiert werden.

Modifizieren jedes Untermoduls

Jetzt fügen wir die Variable __all__ zu jedem Untermodul im structly-Paket hinzu. Dies hilft uns, zu steuern, welche Symbole aus jedem Untermodul exportiert werden, wenn jemand die Anweisung from module import * verwendet.

  1. Zunächst modifizieren wir structure.py:
touch ~/project/structly/structure.py

Dieser Befehl erstellt eine neue Datei namens structure.py im structly-Verzeichnis Ihres Projekts. Nach dem Erstellen der Datei müssen wir die Variable __all__ hinzufügen. Fügen Sie diese Zeile ganz oben in die Datei, direkt nach den Importanweisungen, ein:

__all__ = ['Structure']

Diese Zeile teilt Python mit, dass nur das Symbol Structure importiert wird, wenn jemand from structure import * verwendet. Speichern Sie die Datei und verlassen Sie den Editor.

  1. Als Nächstes modifizieren wir reader.py:
touch ~/project/structly/reader.py

Dieser Befehl erstellt eine neue Datei namens reader.py im structly-Verzeichnis. Durchsuchen Sie nun die Datei, um alle Funktionen zu finden, die mit read_csv_as_ beginnen. Diese Funktionen sind diejenigen, die wir exportieren möchten. Fügen Sie dann eine __all__-Liste mit allen diesen Funktionsnamen hinzu. Sie sollte in etwa so aussehen:

__all__ = ['read_csv_as_instances', 'read_csv_as_dicts', 'read_csv_as_columns']

Beachten Sie, dass die tatsächlichen Funktionsnamen je nach Inhalt der Datei variieren können. Stellen Sie sicher, dass Sie alle read_csv_as_*-Funktionen, die Sie finden, einschließen. Speichern Sie die Datei und verlassen Sie den Editor.

  1. Jetzt modifizieren wir tableformat.py:
touch ~/project/structly/tableformat.py

Dieser Befehl erstellt eine neue Datei namens tableformat.py im structly-Verzeichnis. Fügen Sie diese Zeile ganz oben in die Datei ein:

__all__ = ['create_formatter', 'print_table']

Diese Zeile gibt an, dass nur die Symbole create_formatter und print_table importiert werden, wenn jemand from tableformat import * verwendet. Speichern Sie die Datei und verlassen Sie den Editor.

Einheitliche Imports in __init__.py

Jetzt, da jedes Modul definiert, was es exportiert, können wir die __init__.py-Datei aktualisieren, um alle diese Symbole zu importieren. Die __init__.py-Datei ist eine besondere Datei in Python-Paketen. Sie wird ausgeführt, wenn das Paket importiert wird, und kann verwendet werden, um das Paket zu initialisieren und Symbole aus Untermodulen zu importieren.

touch ~/project/structly/__init__.py

Dieser Befehl erstellt eine neue __init__.py-Datei im structly-Verzeichnis. Ändern Sie den Inhalt der Datei wie folgt:

## structly/__init__.py

from .structure import *
from .reader import *
from .tableformat import *

Diese Zeilen importieren alle exportierten Symbole aus den Untermodulen structure, reader und tableformat. Der Punkt (.) vor den Modulnamen gibt an, dass es sich um relative Imports handelt, d. h. Imports aus dem gleichen Paket. Speichern Sie die Datei und verlassen Sie den Editor.

Testen unserer Änderungen

Erstellen wir eine einfache Testdatei, um zu überprüfen, ob unsere Änderungen funktionieren. Diese Testdatei versucht, die Symbole zu importieren, die wir in den __all__-Variablen angegeben haben, und gibt eine Erfolgsmeldung aus, wenn die Imports erfolgreich sind.

touch ~/project/test_structly.py

Dieser Befehl erstellt eine neue Datei namens test_structly.py im Projektverzeichnis. Fügen Sie den folgenden Inhalt in die Datei ein:

## A simple test to verify our imports work correctly

from structly import Structure
from structly import read_csv_as_instances
from structly import create_formatter, print_table

print("Successfully imported all required symbols!")

Diese Zeilen versuchen, die Klasse Structure, die Funktion read_csv_as_instances sowie die Funktionen create_formatter und print_table aus dem structly-Paket zu importieren. Wenn die Imports erfolgreich sind, wird das Programm die Nachricht "Successfully imported all required symbols!" ausgeben. Speichern Sie die Datei und verlassen Sie den Editor. Jetzt führen wir diesen Test aus:

cd ~/project
python test_structly.py

Der Befehl cd ~/project wechselt das aktuelle Arbeitsverzeichnis in das Projektverzeichnis. Der Befehl python test_structly.py führt das Skript test_structly.py aus. Wenn alles korrekt funktioniert, sollten Sie die Nachricht "Successfully imported all required symbols!" auf dem Bildschirm sehen.

✨ Lösung prüfen und üben

Exportieren aller Symbole aus dem Paket

In Python ist die Organisation von Paketen von entscheidender Bedeutung für die effektive Verwaltung von Code. Jetzt werden wir die Organisation unseres Pakets einen Schritt weiter treiben. Wir werden festlegen, welche Symbole auf Paketebene exportiert werden sollen. Das Exportieren von Symbolen bedeutet, bestimmte Funktionen, Klassen oder Variablen für andere Teile Ihres Codes oder für andere Entwickler, die Ihr Paket verwenden könnten, verfügbar zu machen.

Hinzufügen von __all__ zum Paket

Wenn Sie mit Python-Paketen arbeiten, möchten Sie möglicherweise steuern, welche Symbole zugänglich sind, wenn jemand die Anweisung from structly import * verwendet. Hier kommt die Liste __all__ zum Einsatz. Indem Sie eine __all__-Liste zur __init__.py-Datei des Pakets hinzufügen, können Sie genau steuern, welche Symbole verfügbar sind, wenn jemand die Anweisung from structly import * verwendet.

Zunächst erstellen oder aktualisieren wir die __init__.py-Datei. Wir verwenden den Befehl touch, um die Datei zu erstellen, falls sie noch nicht existiert.

touch ~/project/structly/__init__.py

Öffnen Sie nun die __init__.py-Datei und fügen Sie eine __all__-Liste hinzu. Diese Liste sollte alle Symbole enthalten, die wir exportieren möchten. Die Symbole sind gruppiert nach ihrer Herkunft, z. B. aus den Modulen structure, reader und tableformat.

## structly/__init__.py

from .structure import *
from .reader import *
from .tableformat import *

## Define what symbols are exported when using "from structly import *"
__all__ = ['Structure',  ## from structure
           'read_csv_as_instances', 'read_csv_as_dicts', 'read_csv_as_columns',  ## from reader
           'create_formatter', 'print_table']  ## from tableformat

Nachdem Sie den Code hinzugefügt haben, speichern Sie die Datei und verlassen Sie den Editor.

Verständnis von import *

Das Muster from module import * wird in den meisten Python-Codes im Allgemeinen nicht empfohlen. Es gibt mehrere Gründe dafür:

  1. Es kann Ihren Namensraum mit unerwarteten Symbolen verschmutzen. Dies bedeutet, dass Sie möglicherweise Variablen oder Funktionen in Ihrem aktuellen Namensraum haben, die Sie nicht erwartet haben, was zu Namenskonflikten führen kann.
  2. Es ist unklar, woher bestimmte Symbole stammen. Wenn Sie import * verwenden, ist es schwierig zu sagen, aus welchem Modul ein Symbol stammt, was Ihren Code schwerer zu verstehen und zu warten macht.
  3. Es kann zu Shadowing-Problemen führen. Shadowing tritt auf, wenn eine lokale Variable oder Funktion denselben Namen wie eine Variable oder Funktion aus einem anderen Modul hat, was zu unerwartetem Verhalten führen kann.

Es gibt jedoch bestimmte Fälle, in denen die Verwendung von import * angemessen ist:

  • Für Pakete, die als ein zusammenhängendes Ganzes verwendet werden sollen. Wenn ein Paket als eine Einheit verwendet werden soll, kann die Verwendung von import * den Zugang zu allen erforderlichen Symbolen erleichtern.
  • Wenn ein Paket über __all__ eine klare Schnittstelle definiert. Durch die Verwendung der __all__-Liste können Sie steuern, welche Symbole exportiert werden, was die Verwendung von import * sicherer macht.
  • Für die interaktive Verwendung, z. B. in einer Python-REPL (Read-Eval-Print Loop). In einer interaktiven Umgebung kann es praktisch sein, alle Symbole auf einmal zu importieren.

Testen mit Import *

Um zu überprüfen, dass wir alle Symbole auf einmal importieren können, erstellen wir eine weitere Testdatei. Wir verwenden den Befehl touch, um die Datei zu erstellen.

touch ~/project/test_import_all.py

Öffnen Sie nun die test_import_all.py-Datei und fügen Sie den folgenden Inhalt hinzu. Dieser Code importiert alle Symbole aus dem structly-Paket und testet dann, ob einige der wichtigen Symbole verfügbar sind.

## Test importing everything at once

from structly import *

## Try using the imported symbols
print(f"Structure symbol is available: {Structure is not None}")
print(f"read_csv_as_instances symbol is available: {read_csv_as_instances is not None}")
print(f"create_formatter symbol is available: {create_formatter is not None}")
print(f"print_table symbol is available: {print_table is not None}")

print("All symbols successfully imported!")

Speichern Sie die Datei und verlassen Sie den Editor. Jetzt führen wir den Test aus. Navigieren Sie zunächst mit dem Befehl cd in das Projektverzeichnis und führen Sie dann das Python-Skript aus.

cd ~/project
python test_import_all.py

Wenn alles korrekt eingerichtet ist, sollten Sie eine Bestätigung sehen, dass alle Symbole erfolgreich importiert wurden.

✨ Lösung prüfen und üben

Modulsplitting für eine bessere Codeorganisation

Wenn Ihre Python-Projekte wachsen, können Sie feststellen, dass eine einzelne Moduldatei ziemlich groß wird und mehrere verwandte, aber unterschiedliche Komponenten enthält. In einem solchen Fall ist es eine gute Praxis, das Modul in ein Paket mit Untermodulen aufzuteilen. Dieser Ansatz macht Ihren Code besser organisiert, leichter zu warten und skalierbarer.

Verständnis der aktuellen Struktur

Das Modul tableformat.py ist ein gutes Beispiel für ein großes Modul. Es enthält mehrere Formatiererklassen, die jeweils für die Formatierung von Daten auf unterschiedliche Weise verantwortlich sind:

  • TableFormatter (Basis-Klasse): Dies ist die Basisklasse für alle anderen Formatiererklassen. Sie definiert die grundlegende Struktur und Methoden, die die anderen Klassen erben und implementieren werden.
  • TextTableFormatter: Diese Klasse formatiert Daten im Klartextformat.
  • CSVTableFormatter: Diese Klasse formatiert Daten im CSV-Format (Comma-Separated Values, engl. für "durch Kommas getrennte Werte").
  • HTMLTableFormatter: Diese Klasse formatiert Daten im HTML-Format (Hypertext Markup Language, engl. für "Hypertext-Auszeichnungssprache").

Wir werden dieses Modul in eine Paketstruktur umorganisieren, wobei für jeden Formatierertyp separate Dateien erstellt werden. Dies macht den Code modularer und leichter zu verwalten.

Schritt 1: Bereinigen von Cache-Dateien

Bevor wir mit der Umorganisation des Codes beginnen, ist es eine gute Idee, alle Python-Cache-Dateien zu bereinigen. Diese Dateien werden von Python erstellt, um die Ausführung Ihres Codes zu beschleunigen, können aber manchmal Probleme verursachen, wenn Sie Änderungen an Ihrem Code vornehmen.

cd ~/project/structly
rm -rf __pycache__

In den obigen Befehlen wechselt cd ~/project/structly das aktuelle Verzeichnis in das structly-Verzeichnis Ihres Projekts. rm -rf __pycache__ löscht das __pycache__-Verzeichnis und all seinen Inhalt. Die Option -r steht für rekursiv, was bedeutet, dass alle Dateien und Unterverzeichnisse innerhalb des __pycache__-Verzeichnisses gelöscht werden. Die Option -f steht für force (englisch für "zwingen"), was bedeutet, dass die Dateien ohne Bestätigungsmeldung gelöscht werden.

Schritt 2: Erstellen der neuen Paketstruktur

Jetzt erstellen wir eine neue Verzeichnisstruktur für unser Paket. Wir werden ein Verzeichnis namens tableformat und ein Unterverzeichnis namens formats darin erstellen.

mkdir -p tableformat/formats

Der Befehl mkdir wird verwendet, um Verzeichnisse zu erstellen. Die Option -p steht für parents (englisch für "Eltern"), was bedeutet, dass alle erforderlichen übergeordneten Verzeichnisse erstellt werden, falls sie nicht existieren. Wenn also das tableformat-Verzeichnis nicht existiert, wird es zuerst erstellt, und dann wird das formats-Verzeichnis darin erstellt.

Schritt 3: Verschieben und Umbenennen der ursprünglichen Datei

Als Nächstes verschieben wir die ursprüngliche tableformat.py-Datei in die neue Struktur und benennen sie in formatter.py um.

mv tableformat.py tableformat/formatter.py

Der Befehl mv wird verwendet, um Dateien zu verschieben oder umzubenennen. In diesem Fall verschieben wir die tableformat.py-Datei in das tableformat-Verzeichnis und benennen sie in formatter.py um.

Schritt 4: Aufteilen des Codes in separate Dateien

Jetzt müssen wir Dateien für jeden Formatierer erstellen und den relevanten Code in sie verschieben.

1. Erstellen der Basis-Formatiererdatei

touch tableformat/formatter.py

Der Befehl touch wird verwendet, um eine leere Datei zu erstellen. In diesem Fall erstellen wir eine Datei namens formatter.py im tableformat-Verzeichnis.

Wir werden die Basisklasse TableFormatter und alle allgemeinen Hilfsfunktionen wie print_table und create_formatter in dieser Datei belassen. Die Datei sollte in etwa so aussehen:

## Base TableFormatter class and utility functions

__all__ = ['TableFormatter', 'print_table', 'create_formatter']

class TableFormatter:
    def headings(self, headers):
        '''
        Emit table headings.
        '''
        raise NotImplementedError()

    def row(self, rowdata):
        '''
        Emit a single row of table data.
        '''
        raise NotImplementedError()

def print_table(objects, columns, formatter):
    '''
    Make a nicely formatted table from a list of objects and attribute names.
    '''
    formatter.headings(columns)
    for obj in objects:
        rowdata = [getattr(obj, name) for name in columns]
        formatter.row(rowdata)

def create_formatter(fmt):
    '''
    Create an appropriate formatter given an output format name.
    '''
    if fmt == 'text':
        from .formats.text import TextTableFormatter
        return TextTableFormatter()
    elif fmt == 'csv':
        from .formats.csv import CSVTableFormatter
        return CSVTableFormatter()
    elif fmt == 'html':
        from .formats.html import HTMLTableFormatter
        return HTMLTableFormatter()
    else:
        raise ValueError(f'Unknown format {fmt}')

Die Variable __all__ wird verwendet, um anzugeben, welche Symbole importiert werden sollen, wenn Sie from module import * verwenden. In diesem Fall geben wir an, dass nur die Symbole TableFormatter, print_table und create_formatter importiert werden sollen.

Die Klasse TableFormatter ist die Basisklasse für alle anderen Formatiererklassen. Sie definiert zwei Methoden, headings und row, die von den Unterklassen implementiert werden sollen.

Die Funktion print_table ist eine Hilfsfunktion, die eine Liste von Objekten, eine Liste von Spaltennamen und ein Formatiererobjekt nimmt und die Daten in einer formatierten Tabelle ausgibt.

Die Funktion create_formatter ist eine Fabrikfunktion, die einen Formatnamen als Argument nimmt und ein geeignetes Formatiererobjekt zurückgibt.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben.

2. Erstellen des Text-Formatierers

touch tableformat/formats/text.py

Wir werden nur die Klasse TextTableFormatter in diese Datei hinzufügen.

## Text formatter implementation

__all__ = ['TextTableFormatter']

from ..formatter import TableFormatter

class TextTableFormatter(TableFormatter):
    '''
    Emit a table in plain-text format
    '''
    def headings(self, headers):
        print(' '.join('%10s' % h for h in headers))
        print(('-'*10 + ' ')*len(headers))

    def row(self, rowdata):
        print(' '.join('%10s' % d for d in rowdata))

Die Variable __all__ gibt an, dass nur das Symbol TextTableFormatter importiert werden soll, wenn Sie from module import * verwenden.

Die Anweisung from ..formatter import TableFormatter importiert die Klasse TableFormatter aus der Datei formatter.py im übergeordneten Verzeichnis.

Die Klasse TextTableFormatter erbt von der Klasse TableFormatter und implementiert die Methoden headings und row, um die Daten im Klartextformat zu formatieren.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben.

3. Erstellen des CSV-Formatierers

touch tableformat/formats/csv.py

Wir werden nur die Klasse CSVTableFormatter in diese Datei hinzufügen.

## CSV formatter implementation

__all__ = ['CSVTableFormatter']

from ..formatter import TableFormatter

class CSVTableFormatter(TableFormatter):
    '''
    Output data in CSV format.
    '''
    def headings(self, headers):
        print(','.join(headers))

    def row(self, rowdata):
        print(','.join(str(d) for d in rowdata))

Ähnlich wie in den vorherigen Schritten geben wir die Variable __all__ an, importieren die Klasse TableFormatter und implementieren die Methoden headings und row, um die Daten im CSV-Format zu formatieren.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben.

4. Erstellen des HTML-Formatierers

touch tableformat/formats/html.py

Wir werden nur die Klasse HTMLTableFormatter in diese Datei hinzufügen.

## HTML formatter implementation

__all__ = ['HTMLTableFormatter']

from ..formatter import TableFormatter

class HTMLTableFormatter(TableFormatter):
    '''
    Output data in HTML format.
    '''
    def headings(self, headers):
        print('<tr>', end='')
        for h in headers:
            print(f'<th>{h}</th>', end='')
        print('</tr>')

    def row(self, rowdata):
        print('<tr>', end='')
        for d in rowdata:
            print(f'<td>{d}</td>', end='')
        print('</tr>')

Wir geben erneut die Variable __all__ an, importieren die Klasse TableFormatter und implementieren die Methoden headings und row, um die Daten im HTML-Format zu formatieren.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben.

Schritt 5: Erstellen von Paket-Initialisierungsdateien

In Python werden __init__.py-Dateien verwendet, um Verzeichnisse als Python-Pakete zu markieren. Wir müssen __init__.py-Dateien sowohl im tableformat- als auch im formats-Verzeichnis erstellen.

1. Erstellen einer für das tableformat-Paket

touch tableformat/__init__.py

Fügen Sie den folgenden Inhalt in die Datei ein:

## Re-export the original symbols from tableformat.py
from .formatter import *

Diese Anweisung importiert alle Symbole aus der Datei formatter.py und macht sie verfügbar, wenn Sie das tableformat-Paket importieren.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben.

2. Erstellen einer für das formats-Paket

touch tableformat/formats/__init__.py

Sie können diese Datei leer lassen oder einen einfachen Docstring hinzufügen:

'''
Format implementations for different output formats.
'''

Der Docstring gibt eine kurze Beschreibung darüber, was das formats-Paket macht.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben.

Schritt 6: Testen der neuen Struktur

Erstellen wir einen einfachen Test, um zu überprüfen, ob unsere Änderungen korrekt funktionieren.

cd ~/project
touch test_tableformat.py

Fügen Sie den folgenden Inhalt in die Datei test_tableformat.py ein:

## Test the tableformat package restructuring

from structly import *

## Create formatters of each type
text_fmt = create_formatter('text')
csv_fmt = create_formatter('csv')
html_fmt = create_formatter('html')

## Define some test data
class TestData:
    def __init__(self, name, value):
        self.name = name
        self.value = value

## Create a list of test objects
data = [
    TestData('apple', 10),
    TestData('banana', 20),
    TestData('cherry', 30)
]

## Test text formatter
print("\nText Format:")
print_table(data, ['name', 'value'], text_fmt)

## Test CSV formatter
print("\nCSV Format:")
print_table(data, ['name', 'value'], csv_fmt)

## Test HTML formatter
print("\nHTML Format:")
print_table(data, ['name', 'value'], html_fmt)

Dieser Testcode importiert die erforderlichen Funktionen und Klassen aus dem structly-Paket, erstellt Formatierer jeder Art, definiert einige Testdaten und testet dann jeden Formatierer, indem er die Daten im entsprechenden Format ausgibt.

Speichern Sie die Datei und verlassen Sie den Editor, nachdem Sie diese Änderungen vorgenommen haben. Jetzt führen Sie den Test aus:

python test_tableformat.py

Sie sollten die gleichen Daten in drei verschiedenen Formaten (Text, CSV und HTML) formatiert sehen. Wenn Sie die erwartete Ausgabe sehen, bedeutet dies, dass Ihre Codeumorganisation erfolgreich war.

✨ Lösung prüfen und üben

Zusammenfassung

In diesem Lab haben Sie mehrere wichtige Techniken zur Organisation von Python - Paketen gelernt. Zunächst haben Sie die Verwendung der Variable __all__ beherrscht, um die von einem Modul exportierten Symbole explizit zu definieren. Zweitens haben Sie eine benutzerfreundlichere Paketschnittstelle erstellt, indem Sie Symbole aus Untermodulen vom obersten Paketniveau aus erneut exportiert haben.

Diese Techniken sind unerlässlich für die Erstellung von sauberen, wartbaren und benutzerfreundlichen Python - Paketen. Sie ermöglichen es Ihnen, die Sichtweise des Benutzers zu steuern, den Importprozess zu vereinfachen und den Code logisch zu organisieren, wenn Ihr Projekt wächst.