Python unter Windows FAQ

Wie führe ich unter Windows ein Python-Programm aus?

Das ist nicht unbedingt eine einfache Frage. Bist du mit dem Ausführen von Programmen über die Windows-Befehlszeile schon vertraut, erscheint dir alles selbstverständlich. Andernfalls brauchst du vielleicht etwas mehr Anleitung.

Sofern du keine integrierte Entwicklungsumgebung verwendest, wirst du Windows-Befehle am Ende in ein Fenster tippen, das als „Eingabeaufforderung“ bezeichnet wird. Normalerweise kannst du so ein Fenster über die Suchleiste erzeugen, indem du nach cmd suchst. Du solltest erkennen können, wann du so ein Fenster geöffnet hast, denn du siehst dann eine Windows-„Eingabeaufforderung“, die üblicherweise so aussieht:

C:\>

Der Buchstabe kann ein anderer sein, und dahinter können weitere Dinge stehen, du siehst also genauso leicht etwas wie:

D:\YourName\Projects\Python>

je nachdem, wie dein Computer eingerichtet ist und was du zuletzt mit ihm gemacht hast. Sobald du so ein Fenster geöffnet hast, bist du auf einem guten Weg, Python-Programme auszuführen.

Du musst dir klarmachen, dass deine Python-Skripte von einem anderen Programm verarbeitet werden müssen, dem Python-Interpreter. Der Interpreter liest dein Skript, kompiliert es zu Bytecode und führt den Bytecode dann aus, um dein Programm laufen zu lassen. Wie sorgst du also dafür, dass der Interpreter dein Python verarbeitet?

Zuerst musst du sicherstellen, dass dein Befehlsfenster das Wort „py“ als Anweisung erkennt, den Interpreter zu starten. Hast du ein Befehlsfenster geöffnet, versuche den Befehl py einzugeben und die Eingabetaste zu drücken:

C:\Users\DeinName> py

Du solltest dann etwas sehen wie:

Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32
Tippe "help", "copyright", "credits" oder "license" für mehr Informationen.
>>>

Du hast den Interpreter im „interaktiven Modus“ gestartet. Das bedeutet, dass du Python-Anweisungen oder -Ausdrücke interaktiv eingeben und sie ausführen oder auswerten lassen kannst, während du wartest. Das ist eine der stärksten Eigenschaften von Python. Prüfe es, indem du ein paar Ausdrücke deiner Wahl eingibst und dir die Ergebnisse ansiehst:

>>> print("Hello")
Hello
>>> "Hello" * 3
'HelloHelloHello'

Viele Leute verwenden den interaktiven Modus als bequemen, aber hoch programmierbaren Taschenrechner. Willst du deine interaktive Python-Sitzung beenden, rufe die Funktion exit() auf oder halte die Taste Ctrl gedrückt, während du Z eingibst, und drücke dann die Taste „Enter“, um zu deiner Windows-Eingabeaufforderung zurückzukommen.

Vielleicht hast du auch einen Eintrag im Startmenü wie Start ‣ Programs ‣ Python 3.x ‣ Python (command line), der dazu führt, dass du die Eingabeaufforderung >>> in einem neuen Fenster siehst. Ist das so, verschwindet das Fenster, nachdem du die Funktion exit() aufgerufen oder das Zeichen Ctrl-Z eingegeben hast. Windows führt in dem Fenster einen einzelnen „python“-Befehl aus und schließt es, wenn du den Interpreter beendest.

Jetzt, wo wir wissen, dass der Befehl py erkannt wird, kannst du ihm dein Python-Skript übergeben. Du musst dazu einen absoluten oder einen relativen Pfad zum Python-Skript angeben. Nehmen wir an, dein Python-Skript liegt auf dem Schreibtisch und heißt hello.py, und deine Eingabeaufforderung ist schön in deinem Benutzerverzeichnis geöffnet, sodass du etwas wie dies siehst:

C:\Users\YourName>

Jetzt bittest du also den Befehl py, dein Skript an Python zu übergeben, indem du py gefolgt vom Pfad deines Skripts eintippst:

C:\Users\DeinName> py Desktop\hello.py
hello

Wie kann ich Python-Skripte ausführbar machen?

Unter Windows verknüpft das übliche Python-Installationsprogramm die Endung .py schon mit einem Dateityp (Python.File) und gibt diesem Dateityp einen Öffnen-Befehl, der den Interpreter ausführt (D:\Program Files\Python\python.exe "%1" %*). Das genügt, um Skripte von der Eingabeaufforderung aus als ‚foo.py‘ ausführbar zu machen. Willst du das Skript lieber durch einfaches Eintippen von ‚foo‘ ohne Endung ausführen können, musst du der Umgebungsvariablen PATHEXT .py hinzufügen.

Warum dauert es manchmal so lange, bis Python startet?

Normalerweise startet Python unter Windows sehr schnell, gelegentlich gibt es aber Fehlerberichte, dass Python plötzlich lange zum Starten braucht. Das ist umso verwirrender, weil Python auf anderen Windows-Systemen einwandfrei läuft, die scheinbar genauso eingerichtet sind.

Das Problem kann an einer falschen Konfiguration der Virenprüfsoftware auf der betroffenen Maschine liegen. Von einigen Virenscannern ist bekannt, dass sie den Startaufwand um zwei Größenordnungen erhöhen, wenn der Scanner so eingestellt ist, dass er alle Lesezugriffe auf das Dateisystem überwacht. Prüfe die Konfiguration der Virenprüfsoftware auf deinen Systemen, um sicherzustellen, dass sie wirklich gleich eingerichtet sind. McAfee fällt besonders auf, wenn es so eingestellt ist, dass es alle Lesezugriffe auf das Dateisystem prüft.

Wie kann ich aus einem Python-Skript eine ausführbare Datei erstellen?

Eine Liste von Werkzeugen, mit denen sich ausführbare Dateien erzeugen lassen, steht unter Wie erzeuge ich aus einem Python-Skript eine eigenständige Binärdatei?.

Sind *.pyd-Dateien das gleiche wie eine DLL?

Ja, .pyd-Dateien sind DLLs, es gibt aber einige Unterschiede. Hast du eine DLL namens foo.pyd, dann muss sie eine Funktion PyInit_foo() haben. Du kannst dann in Python „import foo“ schreiben, und Python sucht nach foo.pyd (sowie nach foo.py und foo.pyc) und versucht, wenn es sie findet, PyInit_foo() aufzurufen, um sie zu initialisieren. Du bindest deine .exe nicht mit foo.lib, denn das würde dazu führen, dass Windows das Vorhandensein der DLL verlangt.

Beachte, dass der Suchpfad für foo.pyd PYTHONPATH ist und nicht derselbe wie der Pfad, den Windows zum Suchen von foo.dll verwendet. Außerdem muss foo.pyd zum Ausführen deines Programms nicht vorhanden sein, während eine DLL verlangt wird, wenn du dein Programm mit ihr gebunden hast. Natürlich wird foo.pyd verlangt, wenn du import foo schreiben willst. In einer DLL wird die Bindung im Quellcode mit __declspec(dllexport) deklariert, in einer .pyd wird sie in einer Liste verfügbarer Funktionen festgelegt.

Wie kann ich Python in eine Windows-Anwendung einbinden?

Die Einbettung des Python-Interpreters in eine Windows-Anwendung lässt sich wie folgt zusammenfassen:

  1. Baue Python nicht direkt in deine .exe-Datei ein. Unter Windows muss Python eine DLL sein, um den Import von Modulen zu verarbeiten, die selbst DLLs sind. (Das ist die erste wichtige undokumentierte Tatsache.) Binde stattdessen gegen pythonNN.dll, die typischerweise in C:\Windows\System installiert ist. NN ist die Python-Version, eine Zahl wie „33“ für Python 3.3.

    Du kannst auf zwei verschiedene Weisen gegen Python binden. Binden zur Bindezeit bedeutet, gegen pythonNN.lib zu binden, Binden zur Laufzeit bedeutet, gegen pythonNN.dll zu binden. (Allgemeine Anmerkung: pythonNN.lib ist die sogenannte „import lib“, die zu pythonNN.dll gehört. Sie legt lediglich Symbole für den Binder fest.)

    Binden zur Laufzeit vereinfacht die Bindeoptionen stark, denn alles passiert zur Laufzeit. Dein Code muss pythonNN.dll mit der Windows-Routine LoadLibraryEx() laden. Der Code muss außerdem Zugriffsroutinen und Daten in pythonNN.dll verwenden, also die C-APIs von Python, und zwar über Zeiger, die mit der Windows-Routine GetProcAddress() beschafft werden. Mit Makros lässt sich die Verwendung dieser Zeiger für jeden C-Code transparent machen, der Routinen der C-API von Python aufruft.

  2. Verwendest du SWIG, ist es leicht, ein Python-„Erweiterungsmodul“ zu erzeugen, das die Daten und Methoden der Anwendung für Python verfügbar macht. SWIG erledigt praktisch alle mühsamen Einzelheiten für dich. Das Ergebnis ist C-Code, den du in deine .exe-Datei bindest (!). Du musst keine DLL-Datei erzeugen, und das vereinfacht das Binden ebenfalls.

  3. SWIG erzeugt eine init-Funktion (eine C-Funktion), deren Name vom Namen des Erweiterungsmoduls abhängt. Heißt das Modul zum Beispiel leo, heißt die init-Funktion initleo(). Verwendest du SWIG-Schattenklassen, wie du es tun solltest, heißt die init-Funktion initleoc(). Diese initialisiert eine größtenteils verborgene Hilfsklasse, die von der Schattenklasse verwendet wird.

    Der Grund, warum du den C-Code aus Schritt 2 in deine .exe-Datei binden kannst, ist, dass der Aufruf der Initialisierungsfunktion dem Importieren des Moduls in Python gleichkommt! (Das ist die zweite wichtige undokumentierte Tatsache.)

  4. Kurz gesagt kannst du den folgenden Code verwenden, um den Python-Interpreter mit deinem Erweiterungsmodul zu initialisieren.

    #include <Python.h>
    ...
    Py_Initialize();  // Initialize Python.
    initmyAppc();  // Initialize (import) the helper class.
    PyRun_SimpleString("import myApp");  // Import the shadow class.
    
  5. Es gibt zwei Probleme mit der C-API von Python, die zutage treten, wenn du einen anderen Compiler als MSVC verwendest, den Compiler, mit dem pythonNN.dll gebaut wurde.

    Problem 1: Die sogenannten Funktionen der „sehr hohen Ebene“, die FILE *-Argumente nehmen, funktionieren in einer Umgebung mit mehreren Compilern nicht, weil die Vorstellung jedes Compilers von einem struct FILE unterschiedlich ist. Aus Sicht der Umsetzung sind das Funktionen auf sehr niedriger Ebene.

    Problem 2: SWIG erzeugt den folgenden Code, wenn es Hüllen für void-Funktionen erzeugt:

    Py_INCREF(Py_None);
    _resultobj = Py_None;
    return _resultobj;
    

    Leider ist Py_None ein Makro, das sich zu einem Verweis auf eine komplexe Datenstruktur namens _Py_NoneStruct innerhalb von pythonNN.dll auflöst. Auch dieser Code scheitert in einer Umgebung mit mehreren Compilern. Ersetze solchen Code durch:

    return Py_BuildValue("");
    

    Es ist vielleicht möglich, den Befehl %typemap von SWIG zu verwenden, um die Änderung automatisch vorzunehmen, ich habe das aber nicht zum Funktionieren gebracht (ich bin bei SWIG völliger Anfänger).

  6. Ein Python-Shell-Skript zu verwenden, um aus deiner Windows-Anwendung heraus ein Fenster mit einem Python-Interpreter zu öffnen, ist keine gute Idee. Das entstehende Fenster wäre vom Fenstersystem deiner Anwendung unabhängig. Stattdessen solltest du (oder die Klasse wxPythonWindow) ein „natives“ Interpreter-Fenster erzeugen. Dieses Fenster mit dem Python-Interpreter zu verbinden ist leicht. Du kannst die Ein- und Ausgabe von Python auf _jedes_ Objekt umleiten, das Lesen und Schreiben unterstützt, du brauchst also nur ein Python-Objekt (in deinem Erweiterungsmodul festgelegt), das die Methoden read() und write() enthält.

Wie halte ich andere Editoren davon auf, „Tabs“ in meinen Python-Code zu schreiben?

Die FAQ empfiehlt, keine Tabulatoren zu verwenden, und der Python-Stilleitfaden PEP 8 empfiehlt für verteilten Python-Code 4 Leerzeichen. Das ist auch die Voreinstellung des python-mode von Emacs.

In jedem Editor ist es eine schlechte Idee, Tabulatoren und Leerzeichen zu mischen. MSVC ist in dieser Hinsicht nicht anders und lässt sich leicht auf Leerzeichen einstellen: Gehe auf Tools ‣ Options ‣ Tabs, setze für den Dateityp „Default“ die Werte „Tab size“ und „Indent size“ auf 4 und wähle den Auswahlknopf „Insert spaces“.

Python löst IndentationError oder TabError aus, wenn gemischte Tabulatoren und Leerzeichen im führenden Leerraum Probleme verursachen. Du kannst außerdem das Modul tabnanny ausführen, um einen Verzeichnisbaum im Stapelbetrieb zu prüfen.

Wie prüfe ich auf einen Tastendruck ohne zu blockieren?

Verwende das Modul msvcrt. Das ist ein übliches, Windows-spezifisches Erweiterungsmodul. Es legt eine Funktion kbhit() fest, die prüft, ob ein Tastendruck vorliegt, sowie getch(), die ein Zeichen holt, ohne es auszugeben.

Wie löse ich „missing api-ms-win-crt-runtime-l1-1-0.dll“ Fehler?

Das kann bei Python 3.5 und neuer auftreten, wenn Windows 8.1 oder älter verwendet wird und nicht alle Aktualisierungen installiert sind. Stelle zuerst sicher, dass dein Betriebssystem unterstützt und aktuell ist, und besuche, falls das das Problem nicht löst, die Microsoft-Supportseite für eine Anleitung, wie du die Aktualisierung der C-Laufzeitumgebung von Hand installierst.