Wie kann ich manuell eine .pyc-Datei aus einer .py-Datei generieren?

128

Aus irgendeinem Grund kann ich mich nicht auf Pythons "import" -Anweisung verlassen, um eine .pyc-Datei automatisch zu generieren

Gibt es eine Möglichkeit, eine Funktion wie folgt zu implementieren?

def py_to_pyc(py_filepath, pyc_filepath):
    ...
zJay
quelle

Antworten:

241

Sie können compileallim Terminal verwenden. Der folgende Befehl wird rekursiv in Unterverzeichnisse verschoben und erstellt Pyc-Dateien für alle gefundenen Python-Dateien. Das Compileall- Modul ist Teil der Python-Standardbibliothek, sodass Sie nichts extra installieren müssen, um es zu verwenden. Dies funktioniert genauso für Python2 und Python3.

python -m compileall .
Marwan Alsabbagh
quelle
4
Dies sollte die akzeptierte Antwort sein - zumindest, wenn ich alle * .py in * .pyc kompilieren muss: rekursiv :)
swdev
1
Ist es möglich, eine PYC-Datei zu verteilen, die alle verwendeten Bibliotheken enthält? Benutzer müssen sie also nicht installieren, sondern nur die PYC-Datei ausführen. Ich weiß, dass dies in Java mit JARs möglich ist. Gibt es eine ähnliche Methode für Python?
D. Snap
Ich habe auch etwas über Metadateien in Python gehört. Diese Kompilierung auch einige Cache erstellen? Wenn nicht, wie lautet der Befehl dafür? Da die Endbenutzer keine Schreibberechtigung für das lib-Verzeichnis haben. Und ich möchte die Dinge hier beschleunigen ... PS. Schauen Sie sich auch das -OFlag an, um den Bytecode (.pyo file iso .pyc) zu kompilieren.
Gefahr89
Was ist mit Dekompilieren?
Sajuuk
1
Seien Sie vorsichtig mit diesem Befehl. Ich habe versehentlich einen compileallOrdner in meinem Site-Paket erstellt und alles durcheinander gebracht
Alex,
58

Sie können einzelne Dateien über die Befehlszeile kompilieren mit:

python -m compileall <file_1>.py <file_n>.py
derrend
quelle
55

Es ist schon eine Weile her, seit ich Python das letzte Mal verwendet habe, aber ich glaube, Sie können Folgendes verwenden py_compile:

import py_compile
py_compile.compile("file.py")
Mike Bailey
quelle
8
Sie möchten wahrscheinlich den zweiten Parameter einfügen, der die Ausgabedatei bestimmt. Andernfalls wird standardmäßig so etwas wie verwendet, __pycache__/file.cpython-32.pycund Sie erhalten dies als Rückgabewert.
Rvighne
46

Ich habe verschiedene Möglichkeiten gefunden, Python-Skripte in Bytecode zu kompilieren

  1. Verwendung py_compileim Terminal:

    python -m py_compile File1.py File2.py File3.py ...

    -m Gibt den Namen des zu kompilierenden Moduls an.

    Oder zum interaktiven Zusammenstellen von Dateien

    python -m py_compile -
    File1.py
    File2.py
    File3.py
       .
       .
       .
  2. Verwenden von py_compile.compile:

    import py_compile
    py_compile.compile('YourFileName.py')
  3. Verwenden von py_compile.main():

    Es werden mehrere Dateien gleichzeitig kompiliert.

    import py_compile
    py_compile.main(['File1.py','File2.py','File3.py'])

    Die Liste kann beliebig lang werden. Alternativ können Sie natürlich eine Liste von Dateien in Haupt- oder sogar Dateinamen in Befehlszeilenargumenten übergeben.

    Wenn Sie ['-']main übergeben, können Dateien interaktiv kompiliert werden.

  4. Verwenden von compileall.compile_dir():

    import compileall
    compileall.compile_dir(direname)

    Es kompiliert jede einzelne Python-Datei, die im angegebenen Verzeichnis vorhanden ist.

  5. Verwenden von compileall.compile_file():

    import compileall
    compileall.compile_file('YourFileName.py')

Schauen Sie sich die folgenden Links an:

https://docs.python.org/3/library/py_compile.html

https://docs.python.org/3/library/compileall.html

Abhishek Kashyap
quelle
Eine kleine Korrektur ist, dass der Modulname, den Sie laden, py_compileund compileallNICHT py_compile.pyoder ist compileall.py. Mit anderen Worten, es sollte python3 -m py_compile PYTHON_FILENAMEoder sein python3 -m compileall PYTHON_FILES_DIRECTORY.
Devy
17

Ich würde compileall verwenden . Es funktioniert gut sowohl über Skripte als auch über die Befehlszeile. Es ist ein etwas höheres Modul / Tool als das bereits erwähnte py_compile , das es auch intern verwendet.

Pekka Klärck
quelle
compileallEnthält keine Logik zum Überspringen von Dateien, für die die entsprechende .pycDatei bereits aktuell ist, oder?
Kyle Strand
2
@ KyleStrand compileallüberspringt Dateien, die bereits auf dem neuesten Stand sind .pyc(getestet mit Python 2.7.11)
Eponymous
@Eponymous Interessant. Ich bin mir nicht sicher, warum ich anders gedacht habe. Danke für das Kontrollieren.
Kyle Strand
6

In Python2 können Sie Folgendes verwenden:

python -m compileall <pythonic-project-name>

das macht alle kompilieren .py.pyc in dem Projekt , das die Unterordner enthielt.


In Python3 können Sie Folgendes verwenden:

python3 -m compileall <pythonic-project-name>

das macht alle kompilieren .py__pycache__ Ordner im Projekt , die die Unterordner enthalten.

Oder mit Bräunung von diesem Beitrag :

Sie können das gleiche Layout von erzwingen .pyc Dateien in den Ordnern wie in Python2 erzwingen, indem Sie Folgendes verwenden:

python3 -m compileall -b <pythonic-project-name>

Die Option -blöst die Ausgabe von .pycDateien an ihren Legacy-Speicherorten aus (dh wie in Python2).

Benyamin Jafari
quelle
3

Um den ursprünglichen Fragenanforderungen (Quell- und Zielpfad) zu entsprechen, sollte der Code folgendermaßen aussehen:

import py_compile
py_compile.compile(py_filepath, pyc_filepath)

Wenn der Eingabecode Fehler enthält, wird die Ausnahme py_compile.PyCompileError ausgelöst .

ababak
quelle
1

Es gibt zwei Möglichkeiten, dies zu tun

  1. Befehlszeile
  2. Python-Programm verwenden

Wenn Sie die Befehlszeile verwenden python -m compileall <argument>, kompilieren Sie Python-Code in Python-Binärcode. Ex:python -m compileall -x ./*

Oder Sie können diesen Code verwenden, um Ihre Bibliothek in Bytecode zu kompilieren.

import compileall
import os

lib_path = "your_lib_path"
build_path = "your-dest_path"

compileall.compile_dir(lib_path, force=True, legacy=True)

def compile(cu_path):
    for file in os.listdir(cu_path):
        if os.path.isdir(os.path.join(cu_path, file)):
            compile(os.path.join(cu_path, file))
        elif file.endswith(".pyc"):
            dest = os.path.join(build_path, cu_path ,file)
            os.makedirs(os.path.dirname(dest), exist_ok=True)
            os.rename(os.path.join(cu_path, file), dest)

compile(lib_path)

Blick auf ☞ docs.python.org für ausführliche Dokumentation

Prashant
quelle