Importieren von Modulen in Python - Best Practice


72

Ich bin neu in Python, da ich die Fähigkeiten erweitern möchte, die ich mit R gelernt habe. In RI werden häufig eine Reihe von Bibliotheken geladen, was manchmal zu Konflikten mit Funktionsnamen führt.

Was ist die beste Vorgehensweise in Python? Ich habe einige spezifische Variationen gesehen, zwischen denen ich keinen Unterschied sehe

import pandas, from pandas import *Und from pandas import DataFrame

Was sind die Unterschiede zwischen den ersten beiden und sollte ich nur importieren, was ich brauche. Was wären die schlimmsten Konsequenzen für jemanden, der kleine Programme zur Datenverarbeitung und zur Berechnung einfacher Statistiken erstellt?

AKTUALISIEREN

Ich habe diesen ausgezeichneten Leitfaden gefunden . Es erklärt alles.


1
import pandasund from pandas import DataFramebeide sind okay. Die zweite Form from pandas import *ist normalerweise nicht zu empfehlen, da sie nur alles in den globalen Namespace zieht.
Niklas B.

Antworten:


49

import pandasImportiert das Pandas-Modul unter dem Pandas-Namespace, sodass Sie Objekte innerhalb von Pandas mit aufrufen müssen pandas.foo.

from pandas import *Importiert alle Objekte aus dem Pandas-Modul in Ihren aktuellen Namespace, sodass Sie Objekte innerhalb von Pandas nur mit aufrufen foo. Beachten Sie, dass dies unerwartete Folgen haben kann, wenn zwischen Ihrem aktuellen Namespace und dem Pandas-Namespace Namenskonflikte bestehen.

from pandas import DataFrameist das gleiche wie oben, importiert jedoch nur DataFrame(anstelle von allem) in Ihren aktuellen Namespace.

Meiner Meinung nach ist die erste im Allgemeinen die beste Vorgehensweise, da die verschiedenen Module in Ihrem Code gut unterteilt sind.


44

Nachteil jeder Form

Beim Lesen des Codes anderer Personen (und dieser Personen verwenden sehr unterschiedliche Importstile) sind mir bei jedem der Stile die folgenden Probleme aufgefallen:

import modulewithaverylongnamewird den Code weiter unten mit dem langen Modulnamen (z. B. concurrent.futuresoder django.contrib.auth.backends) überladen und die Lesbarkeit an diesen Stellen verringern.

from module import *gibt mir keine Chance, das zum Beispiel syntaktisch zu sehen classAund classBaus demselben Modul zu kommen und viel miteinander zu tun zu haben. Es macht das Lesen des Codes schwierig . (Dass Namen aus einem solchen Import möglicherweise Namen aus einem früheren Import beschatten, ist der geringste Teil dieses Problems.)

from module import classA, classB, functionC, constantD, functionE Überlastet mein Kurzzeitgedächtnis mit zu vielen Namen, denen ich mental zuweisen modulemuss, um den Code kohärent zu verstehen.

import modulewithaverylongname as mwvlnist mir manchmal nicht ausreichend mnemonisch .

Ein geeigneter Kompromiss

Basierend auf den obigen Beobachtungen habe ich den folgenden Stil in meinem eigenen Code entwickelt:

import moduleist der bevorzugte Stil, wenn der Modulname kurz ist, wie beispielsweise die meisten Pakete in der Standardbibliothek. Dies ist auch der bevorzugte Stil, wenn ich Namen aus dem Modul nur an zwei oder drei Stellen in meinem eigenen Modul verwenden muss. Klarheit übertrumpft dann die Kürze ( "Lesbarkeit zählt" ).

import longername as lnist in fast allen anderen Fällen der bevorzugte Stil. Zum Beispiel könnte ich import django.contrib.auth.backends as djcab. Nach Definition des obigen Kriteriums 1 wird die Abkürzung häufig verwendet und ist daher ausreichend leicht zu merken.

Nur diese beiden Stile sind gemäß "Explizit ist besser als implizit" vollständig pythonisch . Regel.

from module import xxkommt immer noch manchmal in meinem Code vor. Ich benutze es in Fällen, in denen sogar das asFormat übertrieben erscheint. Das bekannteste Beispiel ist from datetime import datetime (aber wenn ich mehr Elemente benötige, werde ich es tun import datetime as dt).


2
Schönes Stück, Lutz . +1 für die Motivation des Profils "Zeitlose Prinzipien" - es ist echt und sehr wichtig im Zeitalter der schleichenden Erosion des Wissens und des sich bewegenden Sandes, auf dem unsere Systeme basieren.
user3666197

Ich bin damit einverstanden, dass dies ein geeigneter Kompromiss ist. Ich verwende from module import xxnur, wenn ich eine eigene Klasse importiere, die in einer anderen Datei definiert ist.
Nicolas Garnier

1
Es ist so langweilig, nicht zu wissen, aus welchem ​​Paket ein bestimmtes Objekt stammt. Der sogenannte geeignete Kompromiss ist eindeutig der richtige Weg, wenn wir "gemeinsam nutzbare" und lesbare Codes erstellen möchten. Übrigens verhindert es auch Namenskonflikte. +1
keepAlive

Wie Sie bevorzuge ich den Import des Moduls, aber wenn das Modul in einem Paket liegt, verwende ich es manchmal from <package> import <module>, insbesondere wenn das Modul mehrere Unterpakete tief ist. Ich würde viel lieber tippen file_generators.Random()als libraries.file_utils.generators.file_generators.Random(), also würde ich nur verwenden from libraries.file_utils.generators import file_generators.
Troy Hoffman

24

Im Allgemeinen ist es besser, explizite Importe durchzuführen. Wie in:

import pandas
frame = pandas.DataFrame()

Oder:

from pandas import DataFrame
frame = DataFrame()

Eine andere Option in Python, wenn Sie widersprüchliche Namen haben, ist der Import von x als y:

from pandas import DataFrame as PDataFrame
from bears import DataFrame as BDataFrame
frame1 = PDataFrame()
frame2 = BDataFrame()

18

Hier sind einige Empfehlungen aus dem PEP8 Style Guide.

  1. Importe sollten normalerweise in getrennten Zeilen erfolgen , z.

    Yes: import os
         import sys
    
    No:  import sys, os
    

    aber es ist okay

    from subprocess import Popen, PIPE
    
  2. Importe werden immer am Anfang der Datei platziert, direkt nach Modulkommentaren und Dokumentzeichenfolgen sowie vor Modulglobalen und -konstanten.

    • Importe sollten in der folgenden Reihenfolge gruppiert werden:
      1. Standardbibliotheksimporte
      2. verwandte Importe von Dritten
      3. lokale anwendungs- / bibliotheksspezifische Importe
    • Sie sollten zwischen jeder Gruppe von Importen eine Leerzeile einfügen.
  3. Absolute Importe werden empfohlen.
    Sie sind besser lesbar und erleichtern das Debuggen, indem sie bessere Fehlermeldungen geben, falls Sie das Importsystem durcheinander bringen.

    import mypkg.sibling
    from mypkg import sibling
    from mypkg.sibling import example
    

    oder explizite relative Importe

    from . import sibling
    from .sibling import example
    
  4. Implizite relative Importe sollten niemals verwendet werden und werden in Python 3 entfernt.

    No:  from ..grand_parent_package import uncle_package
    
  5. Wildcard-Importe ( from <module> import *) sollten vermieden werden , da sie unklar machen, welche Namen im Namespace vorhanden sind, was sowohl die Leser als auch viele automatisierte Tools verwirrt.


Einige Empfehlungen über lazy importsvon Python Speed - Performance - Tipps.

Overhead für Importanweisungen

Importanweisungen können nahezu überall ausgeführt werden. Es ist oft nützlich, sie in Funktionen zu platzieren, um ihre Sichtbarkeit einzuschränken und / oder die anfängliche Startzeit zu verkürzen. Obwohl der Python-Interpreter so optimiert ist, dass nicht dasselbe Modul mehrmals importiert wird, kann das wiederholte Ausführen einer Importanweisung unter bestimmten Umständen die Leistung erheblich beeinträchtigen.

Das unten angegebene Szenario ist auf der Seite erläutert.

>>> def doit1():
... import string
... string.lower('Python')
...
>>> import string
>>> def doit2():
... string.lower('Python')
...
>>> import timeit
>>> t = timeit.Timer(setup='from __main__ import doit1', stmt='doit1()')
>>> t.timeit()
11.479144930839539
>>> t = timeit.Timer(setup='from __main__ import doit2', stmt='doit2()')
>>> t.timeit()
4.6661689281463623

8
from A import B

entspricht im Wesentlichen den folgenden drei Aussagen

import A
B = A.B
del A

Das ist es, das ist alles.


4
Das ist nicht ganz richtig. from A import Bwird Ain den globalen Namespace importiert und Bauch. Sie können immer noch tun A.C(oder auch A.Bwenn Sie B from itertools import imap >>> itertools <module 'itertools' (built-in)> >>> imap itertools.imap >>> itertools.starmap itertools.starmap
möchten

1
Also gibt es nichts del A
Vergleichbares

2

Sie sind alle in unterschiedlichen Kontexten geeignet (weshalb sie alle verfügbar sind). Es gibt kein tiefes Leitprinzip außer allgemeinen Mutterschaftserklärungen zu Klarheit, Wartbarkeit und Einfachheit. Einige Beispiele aus meinem eigenen Code:

  1. import sys, os, re, itertools Vermeidet Namenskollisionen und bietet eine sehr prägnante Möglichkeit, eine Reihe von Standardmodulen zu importieren.
  2. from math import *Lass mich sin(x)statt math.sin(x)in mathematisch schwerem Code schreiben . Das wird ein bisschen heikel, wenn ich auch numpy importiere, was sich bei einigen davon verdoppelt, aber es geht mich nichts an, da es sich im Allgemeinen sowieso um die gleichen Funktionen handelt. Außerdem neige ich dazu, der numpy-Dokumentation zu folgen, die import numpy as npdas Problem vollständig umgeht .
  3. Ich bevorzuge from PIL import Image, ImageDrawnur, weil die PIL-Dokumentation auf diese Weise ihre Beispiele präsentiert.

Wenn Sie wollen , zu tun , sin(x)anstatt , math.sin(x)warum nicht nutzen from math import sin?
Chiggs

@Chiggs: In mathematisch orientiertem Code möchte ich selten nur sin. Wenn ich nur eine Handvoll Symbole möchte, könnte ich jedes als Komma-Liste importieren, aber normalerweise kann ich nicht herausfinden, welche ich benötige. *ist praktisch, wenn auch etwas faul.
Marcelo Cantos
Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.