Лучшие практики для автоматического запуска инструментов генерации кода (например, thrift) в среде Python - PullRequest
0 голосов
/ 03 июля 2018

Я работаю над проектом Python, использующим файлы Thrift для определения структуры сетевых сообщений.

Файлы .thrift (которые определяют структуру сообщений), конечно, проверяются на контроль версий (в моем случае git).

Thrift-компилятор используется для генерации кода на выбор языковых привязок (в моем случае Python) для кодирования и декодирования сообщений на проводе от и к собственным структурам данных Python.

Команда для запуска компилятора:

thrift --gen py encoding.thrift

Компилятор создает новый каталог (gen-py), который содержит сгенерированные файлы Python:

$ find gen-py 
gen-py
gen-py/__init__.py
gen-py/encoding
gen-py/encoding/constants.py
gen-py/encoding/__init__.py
gen-py/encoding/ttypes.py

Хотя есть плюсы и минусы для проверки сгенерированных файлов в системе контроля версий (см., Например, здесь и здесь ), я на стороне забора, который я предпочитаю не проверка сгенерированных файлов в системе управления версиями.

Я относительно новичок в разработке Python. Я пришел из опыта использования в основном скомпилированных языков (например, C ++), которые используют какой-то инструмент сборки (например, make files), где относительно просто добавить некоторые правила в скрипт сборки для запуска thrift-компилятора и генерации языка. привязок.

Мои вопросы:

Какова лучшая практика в Python для автоматического запуска экономичного компилятора и генерации файлов Python?

Если возможно, я хотел бы иметь представление о зависимостях в любом предложенном вами инструменте сборки, чтобы Thrift-компилятор запускался только при необходимости (т. Е. Сгенерированные файлы отсутствуют или файлы .thrift были затронуты с момента последняя сборка).

1 Ответ

0 голосов
/ 03 июля 2018

Вы можете использовать WatchDog , чтобы отслеживать изменения файлов и запускать команду сборки. См. простой пример . Реализуйте подкласс FileSystemEventHandler для просмотра изменений файла.

Вы можете использовать subprocess.run для запуска вашей команды, например:

subprocess.run(["thrift", "--gen", "py", "encoding.thrift"])

РЕДАКТИРОВАТЬ: добавить пример реализации

Вот идея:

import os
import subprocess
import time

from watchdog.events import EVENT_TYPE_CREATED
from watchdog.events import EVENT_TYPE_MODIFIED
from watchdog.events import FileSystemEvent
from watchdog.events import FileSystemEventHandler
from watchdog.observers import Observer


class ThriftHandler(FileSystemEventHandler):

    def on_any_event(self, event):
        # type: (FileSystemEvent) -> None
        if event.event_type in [EVENT_TYPE_CREATED, EVENT_TYPE_MODIFIED]:
            src_path = event.src_path
            if os.path.isfile(src_path) and os.path.splitext(src_path)[1] == ".thrift":
                self.compile_thrift(src_path)
        super(ThriftHandler, self).on_any_event(event)

    def compile_thrift(self, src_path):
        print("Compiling {0}...".format(src_path))
        old_dir = os.curdir
        try:
            os.chdir(os.path.dirname(src_path))
            subprocess.run(["thrift", "--gen", "py", src_path])
        finally:
            os.chdir(old_dir)


def watch_thrift(source_dir):
    event_handler = ThriftHandler()
    observer = Observer()
    observer.schedule(event_handler, source_dir, recursive=True)
    observer.start()
    try:
        while True:
            time.sleep(1)
    except KeyboardInterrupt:
        observer.stop()
    observer.join()


if __name__ == "__main__":
    watch_thrift("dir/to/watch")
...