Come posso generare manualmente un file .pyc da un file .py


128

Per qualche motivo, non posso dipendere dall'istruzione "import" di Python per generare automaticamente il file .pyc

C'è un modo per implementare una funzione come segue?

def py_to_pyc(py_filepath, pyc_filepath):
    ...

Risposte:


241

È possibile utilizzare compileallnel terminale. Il seguente comando andrà ricorsivamente in sottodirectory e creerà file pyc per tutti i file python che trova. Il modulo compileall fa parte della libreria standard di Python, quindi non è necessario installare nulla in più per usarlo. Funziona esattamente allo stesso modo per python2 e python3.

python -m compileall .

4
Questa dovrebbe essere la risposta accettata - almeno nella mia necessità di compilare tutto * .py in * .pyc: ricorsivamente :)
swdev,

1
È possibile distribuire un file PYC contenente tutte le librerie utilizzate? Quindi gli utenti non devono installarli, hanno appena eseguito il file PYC, so che in Java questo è possibile usando un JAR ci sono metodi simili per Python?
D.Spunta il

Ho sentito anche qualcosa sui meta file in Python. Questo compileall crea anche un po 'di cache? In caso contrario, qual è il comando per quello ?? Dal momento che gli utenti finali non hanno il permesso di scrivere nella directory lib. E voglio velocizzare le cose qui ... PS. dai un'occhiata anche alla -Obandiera, per la compilazione bytecode (.pyo file iso .pyc).
danger89,

che dire di decompilare?
Sajuuk,

1
stai attento con questo comando. Ho fatto accidentalmente una compileallcartella sul mio sito-pacchetti e tutto ha rovinato tutto
Alex

58

Puoi compilare singoli file dalla riga di comando con:

python -m compileall <file_1>.py <file_n>.py

55

È passato un po 'di tempo dall'ultima volta che ho usato Python, ma credo che tu possa usare py_compile:

import py_compile
py_compile.compile("file.py")

8
Probabilmente vuoi includere il secondo parametro, che determina il file di output. Altrimenti, il valore predefinito è qualcosa del genere __pycache__/file.cpython-32.pyce lo ottieni come valore di ritorno.
rvighne,

46

Ho trovato diversi modi per compilare script Python in bytecode

  1. Usando py_compilenel terminale:

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

    -m specifica il nome dei moduli da compilare.

    Oppure, per la compilazione interattiva di file

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

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

    Compila diversi file alla volta.

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

    L'elenco può crescere fino a quando lo desideri. In alternativa, puoi ovviamente passare un elenco di file nei nomi dei file principali o addirittura negli argomenti della riga di comando.

    Oppure, se passi ['-']in main, puoi compilare i file in modo interattivo.

  4. Utilizzando compileall.compile_dir():

    import compileall
    compileall.compile_dir(direname)

    Compila tutti i singoli file Python presenti nella directory fornita.

  5. Utilizzando compileall.compile_file():

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

Dai un'occhiata ai link qui sotto:

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

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


Una piccola correzione è che il nome del modulo che stai caricando è py_compilee compileallNON py_compile.pyo compileall.py. In altre parole, dovrebbe essere python3 -m py_compile PYTHON_FILENAMEo python3 -m compileall PYTHON_FILES_DIRECTORY.
Devy,

17

Vorrei usare compileall . Funziona bene sia dagli script che dalla riga di comando. È un modulo / strumento di livello leggermente superiore rispetto al già citato py_compile che utilizza anche internamente.


compileallnon include la logica per saltare i file per i quali il .pycfile corrispondente è già aggiornato, vero?
Kyle Strand,

2
@KyleStrand compileallsalta i file che hanno già un aggiornamento .pyc(testato con Python 2.7.11)
Eponimo

@Eponimo Interessante. Non sono sicuro del perché pensassi diversamente. Grazie per il controllo.
Kyle Strand,

6

In Python2 puoi usare:

python -m compileall <pythonic-project-name>

Il che rende compilare tutti .pyper .pycil progetto che conteneva le sottocartelle.


In Python3 puoi usare:

python3 -m compileall <pythonic-project-name>

che compila tutte .pyle __pycache__cartelle del progetto che contenevano le sottocartelle.

O con browning da questo post :

È possibile applicare lo stesso layout di .pycfile nelle cartelle di Python2 usando:

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

L'opzione -binnesca l'output dei .pycfile nelle loro posizioni legacy (cioè lo stesso di Python2).


3

Per soddisfare i requisiti della domanda originale (percorso di origine e percorso di destinazione), il codice dovrebbe essere simile al seguente:

import py_compile
py_compile.compile(py_filepath, pyc_filepath)

Se il codice di input presenta errori, viene sollevata l' eccezione py_compile.PyCompileError .


1

Esistono due modi per farlo

  1. Riga di comando
  2. Utilizzando il programma Python

Se si utilizza la riga di comando, utilizzare python -m compileall <argument>per compilare il codice Python in codice binario Python. Ex:python -m compileall -x ./*

In alternativa, è possibile utilizzare questo codice per compilare la libreria in codice byte.

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)

consultare ☞ docs.python.org per una documentazione dettagliata

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.