Как я могу вручную сгенерировать файл .pyc из файла .py

129

По какой-то причине я не могу полагаться на оператор Python "import" для автоматического создания файла .pyc.

Есть ли способ реализовать следующую функцию?

def py_to_pyc(py_filepath, pyc_filepath):
    ...
zJay
источник

Ответы:

242

Вы можете использовать compileallв терминале. Следующая команда будет рекурсивно переходить в подкаталоги и создавать файлы pyc для всех найденных файлов python. Модуль compileall является частью стандартной библиотеки python, поэтому вам не нужно ничего устанавливать для его использования. Это работает точно так же для python2 и python3.

python -m compileall .
Марван Альсаббаг
источник
4
Это должен быть принятый ответ - по крайней мере, для меня нужно скомпилировать все * .py в * .pyc: рекурсивно :)
swdev
1
Можно ли распространить файл PYC, содержащий все используемые библиотеки? Таким образом, пользователям не нужно их устанавливать, просто запустил файл PYC, я знаю, что в java это возможно с помощью JAR, есть ли какой-либо аналогичный метод для Python?
D.Snap
Я также слышал кое-что о метафайлах в Python. Этот компилятор также создает какой-то кеш? Если нет, то какая для этого команда ?? Поскольку конечные пользователи не имеют разрешения на запись в каталог lib. И я хочу здесь ускорить ... PS. также обратите внимание на -Oфлаг для компиляции байт-кода (файл .pyo, iso .pyc).
dangerous89
как насчет декомпиляции?
Sajuuk
1
будьте осторожны с этой командой. Я случайно сделал compileallпапку на моем сайте-пакеты, и она все испортила
Alex
58

Вы можете скомпилировать отдельные файлы из командной строки с помощью:

python -m compileall <file_1>.py <file_n>.py
derrend
источник
55

Прошло много времени с тех пор, как я в последний раз использовал Python, но я считаю, что вы можете использовать py_compile:

import py_compile
py_compile.compile("file.py")
Майк Бейли
источник
8
Вероятно, вы захотите включить второй параметр, который определяет выходной файл. В противном случае по умолчанию используется что-то вроде, __pycache__/file.cpython-32.pycи вы получаете это как возвращаемое значение.
rvighne
46

Я нашел несколько способов скомпилировать скрипты Python в байт-код

  1. Использование py_compileв терминале:

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

    -m указывает имя модуля (модулей) для компиляции.

    Или для интерактивной компиляции файлов

    python -m py_compile -
    File1.py
    File2.py
    File3.py
       .
       .
       .
  2. Использование py_compile.compile:

    import py_compile
    py_compile.compile('YourFileName.py')
  3. Использование py_compile.main():

    Он компилирует несколько файлов за раз.

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

    Список может расти сколько угодно долго. В качестве альтернативы, вы можете явно передать список файлов в главном или даже имена файлов в аргументах командной строки.

    Или, если вы перейдете ['-']в main, он может компилировать файлы в интерактивном режиме.

  4. Использование compileall.compile_dir():

    import compileall
    compileall.compile_dir(direname)

    Он компилирует каждый файл Python, присутствующий в предоставленном каталоге.

  5. Использование compileall.compile_file():

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

Взгляните на ссылки ниже:

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

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

Абхишек Кашьяп
источник
Одна небольшая коррекция является то , что имя модуля вы загрузка py_compileи compileallNOT py_compile.pyили compileall.py. Другими словами, должно быть python3 -m py_compile PYTHON_FILENAMEили python3 -m compileall PYTHON_FILES_DIRECTORY.
Devy
17

Я бы использовал compileall . Он прекрасно работает как из скриптов, так и из командной строки. Это модуль / инструмент более высокого уровня, чем уже упомянутый py_compile, который он также использует для внутренних целей.

Пекка Кларк
источник
compileallне включает логику для пропуска файлов, для которых соответствующий .pycфайл уже обновлен, не так ли?
Кайл Стрэнд
2
@KyleStrand compileallделает пропускать файлы , которые уже есть уточненный .pyc(протестировано с Python 2.7.11)
Одноименный
@Eponymous Интересно. Не знаю, почему я думал иначе. Спасибо за проверку.
Кайл Стрэнд
6

В Python2 вы можете использовать:

python -m compileall <pythonic-project-name>

что делает компилировать все , .pyчтобы .pycв проекте , который содержит вложенные папки.


В Python3 вы можете использовать:

python3 -m compileall <pythonic-project-name>

что заставляет компилировать все .pyв __pycache__папки проекта, содержащие вложенные папки.

Или с поджариванием из этого поста :

Вы можете добиться того же расположения .pycфайлов в папках, что и в Python2, используя:

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

Эта опция -bзапускает вывод .pycфайлов в их унаследованные местоположения (т.е. такие же, как в Python2).

Беньямин Джафари
источник
3

Чтобы соответствовать исходным требованиям к вопросу (исходный путь и путь назначения), код должен быть таким:

import py_compile
py_compile.compile(py_filepath, pyc_filepath)

Если во входном коде есть ошибки, возникает исключение py_compile.PyCompileError .

ababak
источник
1

Есть два способа сделать это

  1. Командная строка
  2. Использование программы Python

Если вы используете командную строку, используйте python -m compileall <argument>для компиляции кода Python в двоичный код Python. Пример:python -m compileall -x ./*

Или вы можете использовать этот код для компиляции вашей библиотеки в байт-код.

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)

посмотреть на ☞ docs.python.org для подробной документации

Prashant
источник