我正在做一个Python项目,该项目使用Thrift文件来定义在线网络消息的结构。
.thrift文件(定义消息的结构(当然被签入到版本控制中(在我的例子中是git(。
节俭编译器用于在选择的语言绑定(在我的例子中为 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++(的背景,这些语言使用某种构建工具(例如生成文件(,其中向构建脚本添加一些规则以运行节俭编译器并生成语言绑定相对简单。
我的问题是:
Python中自动运行节俭编译器并生成 Python 文件的最佳实践是什么?
如果可能的话,我希望在您建议的任何构建工具中都有依赖意识,以便仅在必要时运行 thrift 编译器(即生成的文件不存在,或者自上次构建以来已触摸 .thrift 文件(。
您可以使用 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")