it-swarm.com.de

Ich bekomme einen Einrückungsfehler. Wie kann ich das beheben?

Ich habe ein Python-Skript:

if True:
    if False:
        print('foo')
   print('bar')

Wenn ich jedoch versuche, mein Skript auszuführen, löst Python eine IndentationError aus:

  File "script.py", line 4
    print('bar')
               ^
IndentationError: unindent does not match any outer indentation level

Ich habe weiter mit meinem Programm herumgespielt und konnte drei weitere Fehler erzeugen:

  • IndentationError: unexpected indent
  • IndentationError: expected an indented block
  • TabError: inconsistent use of tabs and spaces in indentation

Was bedeuten diese Fehler? Was mache ich falsch? Wie kann ich meinen Code korrigieren?

35
Christian Dean

Warum ist Einrückung wichtig?

In Python wird der Einzug verwendet, um Codeblöcke abzugrenzen. Dies unterscheidet sich von vielen anderen Sprachen, die geschweifte Klammern {} Verwenden, um Blöcke wie Java, Javascript und C abzugrenzen. Aus diesem Grund müssen Python Benutzer genau darauf achten, wann und wie sie Code einrücken, weil Leerzeichen wichtig sind.

Wenn Python auf ein Problem mit dem Einzug Ihres Programms stößt, wird entweder die Ausnahme IndentationError oder TabError ausgelöst =.

Ein bisschen Geschichte

Die historischen Gründe, warum Python Einrückungen im Vergleich zu den wohl allgemein akzeptierten geschweiften Klammern {} Verwendet, sind in einem Artikel aus der Geschichte von Python von Guido) aufgeführt van Rossum - der Schöpfer von Python:

Die Verwendung von Einrückungen in Python stammt direkt aus dem ABC, aber diese Idee entstand nicht aus dem ABC - sie wurde bereits von Donald Knuth beworben und war ein bekanntes Konzept des Programmierstils. (In der Programmiersprache occam wurde es ebenfalls verwendet.) Die Autoren von ABC haben jedoch die Verwendung des Doppelpunkts erfunden, der die Einführungsklausel vom eingerückten Block trennt. Nach einem frühen Benutzertest ohne Doppelpunkt wurde festgestellt, dass Anfängern die Bedeutung der Einrückung nicht klar war, um die ersten Schritte der Programmierung zu lernen. Die Hinzufügung des Doppelpunkts verdeutlichte dies erheblich: Der Doppelpunkt lenkt die Aufmerksamkeit auf das, was folgt, und verknüpft die Phrasen davor und danach auf die richtige Weise.

Wie rücke ich meinen Code ein?

Die Grundregel für das Einrücken von Python-Code (unter Berücksichtigung, dass Sie das gesamte Programm als "Basisblock" behandeln) lautet: Die erste Anweisung in einem Basisblock und jede nachfolgende Anweisung muss von derselben Anweisung eingerückt werden Menge.

Technisch gesehen ist das folgende Python Programm korrekt:

def perm(l):
        # Compute the list of all permutations of l
    if len(l) <= 1:
                  return [l]
    r = []
    for i in range(len(l)):
             s = l[:i] + l[i+1:]
             p = perm(s)
             for x in p:
              r.append(l[i:i+1] + x)
    return r

Wie Sie wahrscheinlich oben sehen können, ist das zufällige Einrücken Ihres Codes extrem schwer zu lesen und dem Programmfluss zu folgen. Es ist besser, konsequent zu sein und einem Stil zu folgen.

PEP8 - Der Python -Stilleitfaden - empfiehlt die Verwendung von vier Leerzeichen pro Einrückungsstufe :

Verwenden Sie 4 Leerzeichen pro Einrückungsstufe.

Das heißt, jede Anweisung, die einen neuen Block startet, und jede nachfolgende Anweisung in dem neuen Block sollten vier Leerzeichen von der aktuellen Einrückungsstufe eingerückt werden. Hier ist das obige Programm, das gemäß dem PEP8-Styleguide eingerückt ist:

def perm(l):
    # Compute the list of all permutations of l
    if len(l) <= 1:
        return [l]
    r = []
    for i in range(len(l)):
        s = l[:i] + l[i+1:]
        p = perm(s)
        for x in p:
            r.append(l[i:i+1] + x)
    return r

Kann ich trotzdem Tabs verwenden?

Python erkennt, dass einige Benutzer Tabulatoren immer noch Leerzeichen vorziehen und dass der Legacy-Code möglicherweise Tabulatoren anstelle von Leerzeichen verwendet, sodass Tabulatoren als Einrückung verwendet werden können. PEP8 geht auf dieses Thema ein :

Leerzeichen sind die bevorzugte Einrückungsmethode.

Tabulatoren sollten nur verwendet werden, um mit Code konsistent zu bleiben, der bereits mit Tabulatoren eingerückt ist.

Beachten Sie jedoch, dass die einzige große Einschränkung darin besteht , nicht beide Tabulatoren und Leerzeichen für Einrückungen zu verwenden. Dies kann zu allen Arten von seltsamen schwer zu debuggenden Einrückungsfehlern führen. Python erweitert Tabulatoren auf die nächste 8. Spalte. Wenn Ihr Editor jedoch auf eine Tabulatorengröße von 4 Spalten eingestellt ist oder Sie Leerzeichen und Tabulatoren verwenden, können Sie problemlos eingerückten Code erstellen, der sieht aus gut in Ihrem Editor, aber Python wird nicht ausgeführt. Der Python 3-Compiler explizit lehnt jedes Programm ab, das eine mehrdeutige Mischung aus Tabulatoren und Leerzeichen enthält, normalerweise durch Erhöhen eines TabError. Standardmäßig ist das Mischen von Tabulatoren und Leerzeichen in Python 2 jedoch weiterhin zulässig. Es wird jedoch dringend empfohlen, diese "Funktion" nicht zu verwenden. Verwenden Sie die Befehlszeilenflags -t Und -tt, Um Python 2 zu erzwingen, um eine Warnung oder (vorzugsweise) einen Fehler auszulösen. PEP8 behandelt auch dieses Thema :

In Python 3 ist es nicht zulässig, Tabulatoren und Leerzeichen zum Einrücken zu verwenden.

Python 2-Code, der mit einer Mischung aus Tabulatoren und Leerzeichen eingerückt ist, sollte so konvertiert werden, dass ausschließlich Leerzeichen verwendet werden.

Beim Aufrufen des Befehlszeileninterpreters Python 2 mit der Option -t werden Warnungen zu Code ausgegeben, der Tabulatoren und Leerzeichen illegal mischt. Bei Verwendung von -tt werden diese Warnungen zu Fehlern. Diese Optionen werden dringend empfohlen!

Was bedeutet "IndentationError: Unerwarteter Einzug"?

Problem

Dieser Fehler tritt auf, wenn eine Anweisung unnötigerweise eingerückt ist oder ihre Einrückung nicht mit der Einrückung früherer Anweisungen im selben Block übereinstimmt. Beispielsweise wird die erste Anweisung im folgenden Programm unnötigerweise eingerückt:

>>>  print('Hello') # this is indented 
  File "<stdin>", line 1
    print('Hello') # this is indented 
    ^
IndentationError: unexpected indent

In diesem Beispiel stimmt die Zeile can_drive = True Im Block if nicht mit dem Einzug einer früheren Anweisung überein:

>>> age = 10
>>> can_drive = None
>>> 
>>> if age >= 18:
...     print('You can drive')
...      can_drive = True # incorrectly indented
  File "<stdin>", line 3
    can_drive = True # incorrectly indented
    ^
IndentationError: unexpected indent

Fix

Die Lösung für diesen Fehler besteht darin, zunächst sicherzustellen, dass die problematische Zeile überhaupt eingerückt werden muss. Zum Beispiel kann das obige Beispiel mit print einfach behoben werden, indem die Zeile nicht mehr eingerückt wird:

>>> print('Hello') # simply unindent the line
Hello

Wenn Sie jedoch sicher sind, dass die Zeile eingerückt werden muss, muss die Einrückung mit der einer früheren Anweisung im selben Block übereinstimmen. Im obigen zweiten Beispiel mit if können wir den Fehler beheben, indem wir sicherstellen, dass die Zeile mit can_drive = True Auf derselben Ebene eingerückt ist wie die vorherigen Anweisungen im Body if:

>>> age = 10
>>> can_drive = None
>>> 
>>> if age >= 18:
...     print('You can drive')
...     can_drive = True # indent this line at the same level.
... 

Was bedeutet "IndentationError: Erwartet einen eingerückten Block"?

Problem

Dieser Fehler tritt auf, wenn Python den 'Header' für eine zusammengesetzte Anweisung sieht, z. B. if <condition>: Oder while <condition>:, Aber den Hauptteil der zusammengesetzten Anweisung oder = block ist niemals definiert. Zum Beispiel haben wir im folgenden Code eine if -Anweisung begonnen, aber wir definieren nie einen Text für die Anweisung:

>>> if True:
... 
  File "<stdin>", line 2

    ^
IndentationError: expected an indented block

In diesem zweiten Beispiel haben wir begonnen, eine for -Schleife zu schreiben, vergessen jedoch, den for -Schleifenkörper einzurücken. Daher erwartet Python immer noch einen eingerückten Block für den Schleifenkörper for:

>>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
... print(name)
  File "<stdin>", line 2
    print(name)
        ^
IndentationError: expected an indented block

Kommentare zählen nicht als Körper:

>>> if True:
...     # TODO
...
  File "<stdin>", line 3

    ^
IndentationError: expected an indented block

Fix

Die Lösung für diesen Fehler besteht darin, einfach einen Textkörper für die zusammengesetzte Anweisung einzufügen.

Wie oben gezeigt, besteht ein häufiger Fehler von neuen Benutzern darin, dass sie vergessen, den Körper einzurücken. Stellen Sie in diesem Fall sicher, dass jede Anweisung, die in den Hauptteil der zusammengesetzten Anweisung aufgenommen werden soll, unter dem Beginn der zusammengesetzten Anweisung auf derselben Ebene eingerückt ist. Hier ist das obige Beispiel behoben:

>>> names = ['sarah', 'lucy', 'michael']
>>> for name in names:
...     print(name) # The for loop body is now correctly indented.
... 
sarah
lucy
michael

Ein anderer häufiger Fall ist, dass ein Benutzer aus irgendeinem Grund möglicherweise keinen tatsächlichen Text für die zusammengesetzte Anweisung definieren möchte oder der Text auskommentiert werden kann. In diesem Fall kann die Anweisung pass verwendet werden. Die pass -Anweisung kann überall dort verwendet werden, wo Python eine oder mehrere Anweisungen als Platzhalter erwartet. Aus der Dokumentation zu pass :

pass ist eine Nulloperation - wenn sie ausgeführt wird, passiert nichts. Es ist als Platzhalter nützlich, wenn eine Anweisung syntaktisch erforderlich ist, aber kein Code ausgeführt werden muss. Beispiel:

def f(arg): pass    # a function that does nothing (yet)

class C: pass       # a class with no methods (yet)

Im folgenden Beispiel wurde die Anweisung if mit dem Schlüsselwort pass korrigiert:

>>> if True:
...     pass # We don't want to define a body.
... 
>>>

Was bedeutet "IndentationError: unindent stimmt nicht mit einer äußeren Einrückungsstufe überein"?

Problem

Dieser Fehler tritt auf, wenn Sie eine Anweisung rückgängig machen, die Einrückungsstufe dieser Anweisung jedoch nicht mit der einer früheren Anweisung übereinstimmt. Im folgenden Code wird beispielsweise der zweite Aufruf von print rückgängig gemacht. Die Einrückungsstufe stimmt jedoch nicht mit der einer früheren Anweisung überein:

>>> if True:
...     if True:
...         print('yes')
...    print()
  File "<stdin>", line 4
    print()
          ^
IndentationError: unindent does not match any outer indentation level

Dieser Fehler ist besonders schwer abzufangen, da bereits ein Leerzeichen zum Fehlschlagen Ihres Codes führt.

Fix

Die Lösung besteht darin, sicherzustellen, dass beim Aufheben der Einrückung die Einrückungsstufe mit der einer früheren Anweisung übereinstimmt. Betrachten Sie das obige Beispiel noch einmal. In diesem Beispiel soll der zweite Aufruf im ersten if -Anweisungshauptteil erfolgen. Ich muss also sicherstellen, dass die Einrückungsstufe dieser Zeile mit der der vorherigen Anweisungen im Hauptteil der ersten if -Anweisung übereinstimmt:

>>> if True:
...     if True:
...         print('yes')
...     print() # indentation level now matches former statement's level.
... 
yes

>>> 

Ich erhalte immer noch einen IndentationError, aber mein Programm scheint korrekt eingerückt zu sein. Was mache ich?

Wenn Ihr Programm visuell korrekt eingerückt zu sein scheint, Sie aber trotzdem ein IndentationError erhalten, haben Sie höchstwahrscheinlich gemischte Tabulatoren mit Leerzeichen . Dies führt manchmal dazu, dass Python seltsame Fehler auslöst. Siehe den Unterabschnitt Sonderfälle unter Was bedeutet "TabError: inkonsistente Verwendung von Tabulatoren und Leerzeichen in Einrückung "Mittelwert? für eine genauere Erläuterung des Problems.

Was bedeutet "TabError: inkonsistente Verwendung von Tabulatoren und Leerzeichen in Einrückungen"?

Problem

Dieser Fehler tritt nur auf, wenn Sie versuchen, Tabulatoren und Leerzeichen als Einrückungszeichen zu mischen. Wie oben erwähnt, lässt Python nicht zu, dass Ihr Programm eine Mischung aus Tabulatoren und Leerzeichen enthält, und löst die spezifische Ausnahme TabError aus, wenn dies der Fall ist. Im folgenden Programm wird beispielsweise eine Mischung aus Tabulatoren und Leerzeichen zum Einrücken verwendet:

>>> if True:
...     if True:
...         print()
...     print()
...     print()
  File "<stdin>", line 5
    print()
          ^
TabError: inconsistent use of tabs and spaces in indentation

Hier ist ein Bild, das das Leerzeichen im obigen Programm visuell zeigt. Graue Punkte sind Leerzeichen und graue Pfeile sind Tabulatoren:

enter image description here

Wir können sehen, dass wir in der Tat gemischte Leerzeichen und Tabulatoren zum Einrücken haben.

Sonderfälle

Hinweis Python wird nicht immer Erhöhe ein TabError wenn Sie mischen Tabulatoren und Leerzeichen in Ihr Programm. Wenn der Programmeinzug eindeutig ist, können mit Python Tabulatoren und Leerzeichen gemischt werden. Zum Beispiel:

>>> if True:
...     if True: # tab
...         pass # tab, then 4 spaces
... 
>>>

Und manchmal drosselt Python einfach die Mischung aus Tabulatoren und Leerzeichen und löst fälschlicherweise eine IndentationError -Ausnahme aus, wenn ein TabError angemessener wäre. Ein anderes Beispiel:

>>> if True:
...     pass # tab
...     pass # 4 spaces
  File "<stdin>", line 3
    pass # 4 spaces
                ^
IndentationError: unindent does not match any outer indentation level

Wie Sie sehen, kann die Ausführung Ihres Codes auf diese Weise mysteriöse Fehler verursachen. Obwohl das Programm visuell in Ordnung zu sein scheint, war Python verwirrt, als er versuchte, die Tabulatoren und Leerzeichen, die für das Einrücken verwendet wurden, zu analysieren, und fehlerhaft.

Dies sind hervorragende Beispiele, die zeigen, warum Tabulatoren und Leerzeichen niemals gemischt werden dürfen und warum die Interpreter-Flags -t Und -tt Verwendet werden, wenn Python 2 verwendet wird.

Fix

Wenn Ihr Programm kurz ist, ist es wahrscheinlich die einfachste und schnellste Lösung, das Programm einfach neu einzurücken. Stellen Sie sicher, dass jede Anweisung mit vier Leerzeichen pro Einrückungsstufe eingerückt ist (siehe Wie rücke ich meinen Code ein?).

Wenn Sie jedoch bereits ein großes Programm haben, in das Sie Tabulatoren und Leerzeichen gemischt haben, gibt es automatisierte Tools, mit denen Sie alle Einrückungen in Leerzeichen umwandeln können.

Viele Editoren wie PyCharm und SublimeText haben Optionen zum automatischen Konvertieren von Tabulatoren in Leerzeichen. Es gibt auch verschiedene Online-Tools wie Tabs To Spaces oder Browserling , mit denen Sie Ihren Code schnell wieder einrücken können. Es gibt auch Tools, die in Python geschrieben wurden. autopep8 kann beispielsweise Ihren Code und andere Einrückungsfehler automatisch neu einrücken.

Selbst die besten Tools können manchmal nicht alle Einrückungsfehler beheben, und Sie müssen sie manuell beheben. Deshalb ist es wichtig, den Code von Anfang an richtig einzurücken.

Ein Hinweis zu "SyntaxError" -bezogenen Einrückungsproblemen

Obwohl dies nicht oft der Fall ist, werden manchmal bestimmte SyntaxError Ausnahmen aufgrund falscher Einrückungen ausgelöst. Schauen Sie sich zum Beispiel den folgenden Code an:

if True:
    pass
pass # oops! this statement should be indented!.
else:
    pass

Wenn der obige Code ausgeführt wird, wird ein SyntaxError is raised:

Traceback (most recent call last):
  File "python", line 4
    else:
       ^
SyntaxError: invalid syntax

Obwohl Python ein SyntaxError auslöst, ist das real Problem mit dem obigen Code, dass die zweite pass Anweisung eingerückt werden sollte. Da das zweite pass nicht eingerückt ist, erkennt Python nicht, dass die vorherige if -Anweisung und die else -Anweisung verbunden werden sollen.

Die Lösung für diesen Fehlertyp besteht darin, den Code einfach richtig einzurücken. Wie Sie Ihren Code richtig einrücken, erfahren Sie im Abschnitt Wie rücke ich meinen Code ein? .

Ich habe immer noch Schwierigkeiten mit der Einrückungssyntax von Python. Was mache ich?

Lassen Sie sich nicht entmutigen, wenn Sie immer noch Probleme haben. Es kann einige Zeit dauern, bis Sie sich an die Python-Regeln für die Whitespace-Syntax gewöhnt haben. Hier einige hilfreiche Tipps:

  • Besorgen Sie sich einen Editor, der Ihnen mitteilt, wenn Sie einen Einrückungsfehler haben. Einige der oben genannten Waren sind: PyCharm , SublimeText und Jupyter Notebook .
  • Wenn Sie Ihren Code einrücken, zählen Sie laut nach, wie oft Sie die Leertaste (oder Tabulatortaste) drücken. Wenn Sie beispielsweise eine Zeile um vier Leerzeichen einrücken müssen, sagen Sie laut " eins, zwei, drei, vier "bei gleichzeitigem Drücken der Leertaste. Es klingt albern, aber es hilft Ihrem Gehirn, darüber nachzudenken, wie tief Sie Ihren Code einrücken.
  • Wenn Sie einen Editor haben, prüfen Sie, ob dieser die Option hat, Tabulatoren automatisch in Leerzeichen umzuwandeln.
  • Zeigen Sie den Code anderer an. Durchsuchen Sie github oder Stackoverflow und sehen Sie sich Beispiele für Python-Code an.
  • Einfach Code schreiben. Das ist der beste Weg, um besser zu werden. Je mehr Sie Python Code schreiben, desto besser werden Sie.

Verwendete Ressourcen

54
Christian Dean

Erhabener Text 3

Wenn Sie in Sublime Text 3 codieren, kann dies bei Problemen mit Einrückungen helfen

In Sublime Text während der Bearbeitung einer Python-Datei:

Sublime Textmenü>Voreinstellungen>Einstellungen - Syntaxspezifisch:

Python.sublime-einstellungen

{
    "tab_size": 4,
    "translate_tabs_to_spaces": true
}
1
chebaby

Schnelle Lösung für Sublime-Benutzer:

  1. Drücken Sie Strg-H, um auf Suchen und Ersetzen zuzugreifen 
  2. In Suchen: Geben Sie 4 Leerzeichen ein
  3. In Ersetzen: Kopieren Sie eine Registerkarte aus Ihrem Code und fügen Sie sie dort ein
0
Matthew Park

Sie sehen, Sie haben einen winzigen Fehler.

if True:
    if False:
        print('foo')
   print('bar')

Sie sollten tun:

if True:
    if False:
        print('foo')
    print('bar')

Wie Sie sehen können, ist Ihr Druck nur 3 Leerzeichen eingerückt, es wird angenommen, dass er 4 Leerzeichen eingerückt ist.

0
The Coder