Як я можу вручну генерувати .pyc файл із файлу .py


128

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

Чи є спосіб реалізувати функцію наступним чином?

def py_to_pyc(py_filepath, pyc_filepath):
    ...

Відповіді:


241

Ви можете використовувати compileallв терміналі. Наступна команда буде рекурсивно переходити в підкаталоги та робити файли pyc для всіх знайдених файлів python. Модуль компіляції є частиною стандартної бібліотеки 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).
небезпека89

як щодо декомпіляції?
Саджук

1
будьте обережні з цією командою. Я випадково зробив у compileallсвоїй папці пакунків сайти, і це зіпсувало все
Алекс

58

Можна компілювати окремі файли (файли) з командного рядка за допомогою:

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

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'])

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

    Або, якщо ви переходите ['-']в основний, то він може збирати файли інтерактивно.

  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 .


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)

див. at docs.python.org для отримання детальної документації

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.