Como posso gerar manualmente um arquivo .pyc a partir de um arquivo .py


128

Por alguma razão, não posso depender da instrução "import" do Python para gerar o arquivo .pyc automaticamente

Existe uma maneira de implementar uma função da seguinte maneira?

def py_to_pyc(py_filepath, pyc_filepath):
    ...

Respostas:


241

Você pode usar compileallno terminal. O comando a seguir irá recursivamente para subdiretórios e criará arquivos pyc para todos os arquivos python encontrados. O módulo compileall faz parte da biblioteca padrão do python, portanto você não precisa instalar nada extra para usá-lo. Isso funciona exatamente da mesma maneira para python2 e python3.

python -m compileall .

4
Esta deve ser a resposta aceita --at menos na minha necessidade de compilar todos py * em * .pyc: recursivamente :)
swdev

1
É possível distribuir um arquivo PYC contendo todas as bibliotecas usadas? Então, os usuários não precisam instalá-los, apenas executaram o arquivo PYC, eu sei que em java isso é possível usando JARs. Existe algum método semelhante para o Python?
D.Snap

Também ouvi algo sobre metarquivos em Python. Este compileall também constrói algum cache? Se não, qual é o comando para isso? Como os usuários finais não têm permissão de gravação no diretório lib. E eu quero acelerar as coisas aqui ... PS. também dê uma olhada na -Oflag, para compilação de bytecode (.pyo file iso .pyc).
danger89

que tal descompilar?
precisa saber é o seguinte

1
tenha cuidado com este comando. Eu tinha acidentalmente fazer um compileallno meu site-pacotes de pasta e sujou-se tudo
Alex

58

Você pode compilar arquivos individuais na linha de comando com:

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

55

Já faz um tempo desde a última vez que usei o Python, mas acredito que você pode usar py_compile:

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

8
Você provavelmente deseja incluir o segundo parâmetro, que determina o arquivo de saída. Caso contrário, o padrão é algo como __pycache__/file.cpython-32.pyce você obtém isso como o valor de retorno.
precisa saber é o seguinte

46

Encontrei várias maneiras de compilar scripts python no bytecode

  1. Usando py_compileno terminal:

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

    -m especifica o nome do (s) módulo (s) a ser compilado.

    Ou, para compilação interativa de arquivos

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

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

    Compila vários arquivos por vez.

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

    A lista pode crescer enquanto você desejar. Como alternativa, você pode obviamente passar uma lista de arquivos nos nomes principais ou pares de arquivos na linha de comando args.

    Ou, se você passar ['-']no main, ele poderá compilar arquivos interativamente.

  4. Usando compileall.compile_dir():

    import compileall
    compileall.compile_dir(direname)

    Ele compila todos os arquivos Python presentes no diretório fornecido.

  5. Usando compileall.compile_file():

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

Dê uma olhada nos links abaixo:

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

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


Uma pequena correção é que o nome do módulo que você está carregando é py_compilee compileallNÃO py_compile.pyou compileall.py. Em outras palavras, deveria ser python3 -m py_compile PYTHON_FILENAMEou python3 -m compileall PYTHON_FILES_DIRECTORY.
precisa

17

Eu usaria compileall . Funciona bem tanto a partir de scripts quanto a partir da linha de comando. É um módulo / ferramenta de nível um pouco mais alto do que o py_compile já mencionado que ele também usa internamente.


compileallnão inclui lógica para ignorar arquivos para os quais o .pycarquivo correspondente já está atualizado, não é?
Kyle Strand

2
O @KyleStrand compileallignora arquivos que já possuem uma atualização .pyc(testada com o Python 2.7.11) #
1812

Interessante @Eponymous. Não sei por que pensei o contrário. Obrigado por verificar.
Kyle Strand

6

No Python2 você pode usar:

python -m compileall <pythonic-project-name>

que faz com que compilar tudo .pypara .pycno projeto que continha as subpastas.


No Python3 você pode usar:

python3 -m compileall <pythonic-project-name>

o que compila tudo .pynas __pycache__pastas do projeto que continham as subpastas.

Ou com escurecimento deste post :

Você pode aplicar o mesmo layout de .pycarquivos nas pastas que no Python2 usando:

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

A opção -baciona a saída dos .pycarquivos para seus locais herdados (ou seja, o mesmo que no Python2).


3

Para corresponder aos requisitos da pergunta original (caminho de origem e destino), o código deve ser o seguinte:

import py_compile
py_compile.compile(py_filepath, pyc_filepath)

Se o código de entrada tiver erros, a exceção py_compile.PyCompileError será gerada.


1

Há duas maneiras de fazer isso

  1. Linha de comando
  2. Usando o programa python

Se você estiver usando a linha de comando, use python -m compileall <argument>para compilar o código python em código binário python. Ex:python -m compileall -x ./*

Ou, você pode usar esse código para compilar sua biblioteca em código de bytes.

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)

consulte ☞docs.python.org para obter documentação detalhada

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.