自动将 protobuf 规范编译到 setup.py 中的 python 类中

2023-11-26

我有一个 python 项目,它使用 google protobufs 作为通过网络进行通信的消息格式。使用以下命令可以直接从 .proto 文件生成 python 文件protoc程序。我该如何配置我的setup.py项目文件,以便它自动调用protoc命令?


在类似的情况下,我最终得到了这段代码(setup.py,但以允许提取到某些外部 Python 模块以供重用的方式编写)。请注意,我从 protobuf 源代码发行版的 setup.py 文件中获取了generate_proto 函数和一些想法。

from __future__ import print_function

import os
import shutil
import subprocess
import sys

from distutils.command.build_py import build_py as _build_py
from distutils.command.clean import clean as _clean
from distutils.debug import DEBUG
from distutils.dist import Distribution
from distutils.spawn import find_executable
from nose.commands import nosetests as _nosetests
from setuptools import setup

PROTO_FILES = [
    'goobuntu/proto/hoststatus.proto',
    ]

CLEANUP_SUFFIXES = [
    # filepath suffixes of files to remove on "clean" subcommand
    '_pb2.py',
    '.pyc',
    '.so',
    '.o',
    'dependency_links.txt',
    'entry_points.txt',
    'PKG-INFO',
    'top_level.txt',
    'SOURCES.txt',
    '.coverage',
    'protobuf/compiler/__init__.py',
    ]

CLEANUP_DIRECTORIES = [  # subdirectories to remove on "clean" subcommand
    # 'build'  # Note: the build subdirectory is removed if --all is set.
    'html-coverage',
    ]

if 'PROTOC' in os.environ and os.path.exists(os.environ['PROTOC']):
  protoc = os.environ['PROTOC']
else:
  protoc = find_executable('protoc')


def generate_proto(source):
  """Invoke Protocol Compiler to generate python from given source .proto."""
  if not os.path.exists(source):
    sys.stderr.write('Can\'t find required file: %s\n' % source)
    sys.exit(1)

  output = source.replace('.proto', '_pb2.py')
  if (not os.path.exists(output) or
      (os.path.getmtime(source) > os.path.getmtime(output))):
    if DEBUG:
      print('Generating %s' % output)

    if protoc is None:
      sys.stderr.write(
          'protoc not found. Is protobuf-compiler installed? \n'
          'Alternatively, you can point the PROTOC environment variable at a '
          'local version.')
      sys.exit(1)

    protoc_command = [protoc, '-I.', '--python_out=.', source]
    if subprocess.call(protoc_command) != 0:
      sys.exit(1)


class MyDistribution(Distribution):
  # Helper class to add the ability to set a few extra arguments
  # in setup():
  # protofiles : Protocol buffer definitions that need compiling
  # cleansuffixes : Filename suffixes (might be full names) to remove when
  #                   "clean" is called
  # cleandirectories : Directories to remove during cleanup
  # Also, the class sets the clean, build_py, test and nosetests cmdclass
  # options to defaults that compile protobufs, implement test as nosetests
  # and enables the nosetests command as well as using our cleanup class.

  def __init__(self, attrs=None):
    self.protofiles = []  # default to no protobuf files
    self.cleansuffixes = ['_pb2.py', '.pyc']  # default to clean generated files
    self.cleandirectories = ['html-coverage']  # clean out coverage directory
    cmdclass = attrs.get('cmdclass')
    if not cmdclass:
      cmdclass = {}
    # These should actually modify attrs['cmdclass'], as we assigned the
    # mutable dict to cmdclass without copying it.
    if 'nosetests' not in cmdclass:
      cmdclass['nosetests'] = MyNosetests
    if 'test' not in cmdclass:
      cmdclass['test'] = MyNosetests
    if 'build_py' not in cmdclass:
      cmdclass['build_py'] = MyBuildPy
    if 'clean' not in cmdclass:
      cmdclass['clean'] = MyClean
    attrs['cmdclass'] = cmdclass
    # call parent __init__ in old style class
    Distribution.__init__(self, attrs)


class MyClean(_clean):

  def run(self):
    try:
      cleandirectories = self.distribution.cleandirectories
    except AttributeError:
      sys.stderr.write(
          'Error: cleandirectories not defined. MyDistribution not used?')
      sys.exit(1)
    try:
      cleansuffixes = self.distribution.cleansuffixes
    except AttributeError:
      sys.stderr.write(
          'Error: cleansuffixes not defined. MyDistribution not used?')
      sys.exit(1)
    # Remove build and html-coverage directories if they exist
    for directory in cleandirectories:
      if os.path.exists(directory):
        if DEBUG:
          print('Removing directory: "{}"'.format(directory))
        shutil.rmtree(directory)
    # Delete generated files in code tree.
    for dirpath, _, filenames in os.walk('.'):
      for filename in filenames:
        filepath = os.path.join(dirpath, filename)
        for i in cleansuffixes:
          if filepath.endswith(i):
            if DEBUG:
              print('Removing file: "{}"'.format(filepath))
            os.remove(filepath)
    # _clean is an old-style class, so super() doesn't work
    _clean.run(self)


class MyBuildPy(_build_py):

  def run(self):
    try:
      protofiles = self.distribution.protofiles
    except AttributeError:
      sys.stderr.write(
          'Error: protofiles not defined. MyDistribution not used?')
      sys.exit(1)
    for proto in protofiles:
      generate_proto(proto)
    # _build_py is an old-style class, so super() doesn't work
    _build_py.run(self)


class MyNosetests(_nosetests):

  def run(self):
    try:
      protofiles = self.distribution.protofiles
    except AttributeError:
      sys.stderr.write(
          'Error: protofiles not defined. MyDistribution not used?')
    for proto in protofiles:
      generate_proto(proto)
    # _nosetests is an old-style class, so super() doesn't work
    _nosetests.run(self)


setup(
    # MyDistribution automatically enables several extensions, including
    # the compilation of protobuf files.
    distclass=MyDistribution,
    ...
    tests_require=['nose'],
    protofiles=PROTO_FILES,
    cleansuffixes=CLEANUP_SUFFIXES,
    cleandirectories=CLEANUP_DIRECTORIES,
    )
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

自动将 protobuf 规范编译到 setup.py 中的 python 类中 的相关文章

  • 是否有解决方法可以通过 CoinGecko API 安全检查?

    我在工作中运行我的代码 一切都很顺利 但在不同的网络 家庭 WiFi 上 我不断收到403访问时出错CoinGecko V3 API https www coingecko com api documentations v3 可以观察到 在
  • Django 的内联管理:一个“预填充”字段

    我正在开发我的第一个 Django 项目 我希望用户能够在管理中创建自定义表单 并向其中添加字段当他或她需要它们时 为此 我在我的项目中添加了一个可重用的应用程序 可在 github 上找到 https github com stephen
  • 元组有什么用?

    我现在正在学习 Python 课程 我们刚刚介绍了元组作为数据类型之一 我阅读了它的维基百科页面 但是 我无法弄清楚这种数据类型在实践中会有什么用处 我可以提供一些需要一组不可变数字的示例吗 也许是在 Python 中 这与列表有何不同 每
  • Python 中的哈希映射

    我想用Python实现HashMap 我想请求用户输入 根据他的输入 我从 HashMap 中检索一些信息 如果用户输入HashMap的某个键 我想检索相应的值 如何在 Python 中实现此功能 HashMap
  • 如何使用 opencv.omnidir 模块对鱼眼图像进行去扭曲

    我正在尝试使用全向模块 http docs opencv org trunk db dd2 namespacecv 1 1omnidir html用于对鱼眼图像进行扭曲处理Python 我正在尝试适应这一点C 教程 http docs op
  • 安装了 32 位的 Python,显示为 64 位

    我需要运行 32 位版本的 Python 我认为这就是我在我的机器上运行的 因为这是我下载的安装程序 当我重新运行安装程序时 它会将当前安装的 Python 版本称为 Python 3 5 32 位 然而当我跑步时platform arch
  • 将html数据解析成python列表进行操作

    我正在尝试读取 html 网站并提取其数据 例如 我想查看公司过去 5 年的 EPS 每股收益 基本上 我可以读入它 并且可以使用 BeautifulSoup 或 html2text 创建一个巨大的文本块 然后我想搜索该文件 我一直在使用
  • Pandas/Google BigQuery:架构不匹配导致上传失败

    我的谷歌表中的架构如下所示 price datetime DATETIME symbol STRING bid open FLOAT bid high FLOAT bid low FLOAT bid close FLOAT ask open
  • 需要在python中找到print或printf的源代码[关闭]

    很难说出这里问的是什么 这个问题是含糊的 模糊的 不完整的 过于宽泛的或修辞性的 无法以目前的形式得到合理的回答 如需帮助澄清此问题以便重新打开 访问帮助中心 help reopen questions 我正在做一些我不能完全谈论的事情 我
  • 使用 xlrd 打开 BytesIO (xlsx)

    我正在使用 Django 需要读取上传的 xlsx 文件的工作表和单元格 使用 xlrd 应该可以 但因为文件必须保留在内存中并且可能不会保存到我不知道如何继续的位置 本例中的起点是一个带有上传输入和提交按钮的网页 提交后 文件被捕获req
  • Python beautifulsoup 仅限 1 级文本

    我看过其他 beautifulsoup 得到相同级别类型的问题 看来我的有点不同 这是网站 我正试图拿到右边那张桌子 请注意表的第一行如何展开为该数据的详细细分 我不想要那个数据 我只想要最顶层的数据 您还可以看到其他行也可以展开 但在本例
  • “隐藏”内置类对象、函数、代码等的名称和性质[关闭]

    Closed 这个问题需要多问focused help closed questions 目前不接受答案 我很好奇模块中存在的类builtins无法直接访问的 例如 type lambda 0 name function of module
  • 在 Sphinx 文档中*仅*显示文档字符串?

    Sphinx有一个功能叫做automethod从方法的文档字符串中提取文档并将其嵌入到文档中 但它不仅嵌入了文档字符串 还嵌入了方法签名 名称 参数 我如何嵌入only文档字符串 不包括方法签名 ref http www sphinx do
  • 不同编程语言中的浮点数学

    我知道浮点数学充其量可能是丑陋的 但我想知道是否有人可以解释以下怪癖 在大多数编程语言中 我测试了 0 4 到 0 2 的加法会产生轻微的错误 而 0 4 0 1 0 1 则不会产生错误 两者计算不平等的原因是什么 在各自的编程语言中可以采
  • 仅第一个加载的 Django 站点有效

    我最近向 stackoverflow 提交了一个问题 标题为使用mod wsgi在apache上多次请求后Django无限加载 https stackoverflow com questions 71705909 django infini
  • 如何断言 Unittest 上的可迭代对象不为空?

    向服务提交查询后 我会收到一本字典或一个列表 我想确保它不为空 我使用Python 2 7 我很惊讶没有任何assertEmpty方法为unittest TestCase类实例 现有的替代方案看起来并不正确 self assertTrue
  • 实现 XGboost 自定义目标函数

    我正在尝试使用 XGboost 实现自定义目标函数 在 R 中 但我也使用 python 所以有关 python 的任何反馈也很好 我创建了一个返回梯度和粗麻布的函数 它工作正常 但是当我尝试运行 xgb train 时它不起作用 然后 我
  • 使用for循环时如何获取前一个元素? [复制]

    这个问题在这里已经有答案了 可能的重复 Python 循环内的上一个和下一个值 https stackoverflow com questions 1011938 python previous and next values inside
  • 如何应用一个函数 n 次? [关闭]

    Closed 这个问题需要细节或清晰度 help closed questions 目前不接受答案 假设我有一个函数 它接受一个参数并返回相同类型的结果 def increment x return x 1 如何制作高阶函数repeat可以
  • Kivy - 单击按钮时编辑标签

    我希望 Button1 在单击时编辑标签 etykietka 但我不知道如何操作 你有什么想法吗 class Zastepstwa App def build self lista WebOps getList layout BoxLayo

随机推荐

  • 如何编写一个通用的可变参数 lambda 来丢弃其参数?

    我想编写一个 lambda 它通过通用引用接受任意数量的参数并完全忽略它们 显而易见的方法是使用可变参数通用参数包的语法并省略参数名称 auto my lambda auto return 42 这工作正常 使用 gcc 4 9 2 直到我
  • 什么是实物签名约束

    如果我检查kind of Maybe我明白了 gt k Maybe Maybe gt 现在 如果我检查那种Monad我明白了 gt k Monad Monad gt gt Constraint What is Constraint那里以及为
  • 如何从 Google App Engine High Replication 数据存储区导出数据?

    我正在考虑在一个项目中使用 Google App Engine 并且希望确保在我决定离开 GAE 或 GAE 关闭 时能够导出所有数据 我搜索的有关从 GAE 导出数据的所有内容都指向https developers google com
  • 在 SQL Server 中远程调用表值函数的解决方法存在更多问题

    我有一个包含一组参数的查询 需要使用不同的参数多次运行 因此我将其包装在表值函数中 该表值函数需要从远程服务器调用 不幸的是 调用在链接服务器上失败并出现错误 Msg 4122 Level 16 State 1 Line 29 Remote
  • 滚动嵌入 HTML 的 PDF

    我已在 Iframe 中嵌入了 PDF 文件 我的 html 文件有按钮 向上 向下 当我单击这些按钮时 我希望 pdf 向上或向下滚动 有没有办法用javascript或任何其他方式控制pdf 我将为此应用程序使用 Internet Ex
  • 应该编写文本处理 DCG 来处理代码或字符吗?或两者?

    在 Prolog 中 传统上有两种表示字符序列的方法 作为列表chars 它们是长度为 1 的原子 作为列表codes 它们只是整数 整数将被解释为代码点 但要应用的约定未指定 作为一个 非常理智的 例子 在 SWI Prolog 中 代码
  • 如何使用 OKHTTP 取消请求

    我需要能够MANAGER一些请求与OKHTTP 使用Google Places AutoComplete通过输入地址来接收一些预测 这问题是每次我插入一个CHAR它会提出一个新的请求 但同时我需要取消前一个请求 例如 纽约市 同时有 13
  • 在java中使用10个线程打印1到100

    我是多线程新手 我有一个问题是在 Java 中使用 10 个线程在以下约束下打印 1 到 100 Thread t1应该打印 1 11 21 31 91 t2应该打印 2 12 22 32 92 likewise t10应该打印 10 20
  • 如何仅使用脚本创建自制公式

    我想将一些 shell 脚本 支持文件打包成一个自制程序 将这些脚本安装在用户的某个地方 PATH 我将用我自己的水龙头提供配方 阅读通过配方食谱这些示例似乎假设上游库中存在 cmake 或 autotools 系统 如果我的项目仅包含几个
  • htaccess 重定向 + 隐藏 url 中的子文件夹

    我环顾四周并尝试了一些有效的规则和条件 虽然有些不起作用 或者条件会捕获太多导致其他域也重定向 这对我有用 Redirect also catches www RewriteCond HTTP HOST www domain com Rew
  • TBN 矩阵中的法向量、切向量和双切向量总是垂直的吗?

    这与另一个问题中描述的问题有关 那里有图片 Opengl 着色器问题 奇怪的光反射伪像 我有一个 obj 导入器 它创建数据结构并计算切线和双切线 这是我的对象中第一个三角形的数据 我对切线空间的理解是 法线从顶点向外指向 切线垂直 正交
  • Java - 匿名内部类生命周期

    当使用匿名内部类作为 PropertyChangeListener 时 该类会在对象生命周期的哪个点被垃圾回收 包含类 SettingsNode 被回收后 我是否应该显式删除包含类 SettingsNode 的终结器中的 PropertyC
  • forking() 和 CreateProcess()

    forking 和 CreateProcess 带有所有必需的参数 对于 Linux 和 WinXP 来说分别是一样的吗 如果它们不同 那么有人可以解释这两种情况下发生的情况的差异吗 Thanks 他们在不同的系统上做不同的事情 Creat
  • 将列转换为行并保留列名称

    R 有什么方法可以将列转换为行并保留列的名称吗 输入示例 A B 1 1 2 3 3 4 44 5 Output Group Number A 1 A 2 A 3 A 44 B 1 B 3 B 4 B 5 无需使用reshape2 您可以使
  • jQuery - 如何选择除特定复选框之外的所有复选框?

    我有一个 jQuery 选择器 看起来像这样 input checkbox click function event DO STUFF HERE 一切都运行良好 直到我被要求添加另一个与原始复选框无关的复选框 如何为除一个复选框之外的所有复
  • 如何创建不依赖于 C 运行时的 Win32 DLL

    使用 Visual Studio 2008 及其 C C 编译器 如何创建仅依赖于其他 Windows DLL 而不依赖于 Microsoft C 运行时的 Win32 DLL 我想将一些 C 代码放入完全计算的 DLL 中 并且几乎不使用
  • Java常量池的用途是什么?

    我目前正在尝试更深入地研究Java虚拟机的规范 我一直在阅读 JVM 内幕 在线书籍有一个令人困惑的抽象我似乎无法理解 常量池 以下是这本书的摘录 对于它加载的每种类型 Java 虚拟机必须存储一个常量池 常量池是类型使用的一组有序常量 包
  • 为什么 android InputMethodManager.showSoftInput() 返回 false?

    最近在开发应用程序时 我遇到了一个问题 我在谷歌上搜索了很多 但找不到任何解决方案 最后我遇到了这个Android 问题跟踪器 为了解释我的问题 我制作了一个示例应用程序 我的示例应用程序的基本工作 我有一个屏幕 其中有一个 EditTex
  • ubuntu18.04上的pyside2安装问题,anaconda上的python 3.8.3

    安装完anaconda3后 开始安装pyside2 我直接输入pip install pyside2 并成功安装pyside2 5 15 但是当我运行玩具示例时 发生了错误 Traceback most recent call last F
  • 自动将 protobuf 规范编译到 setup.py 中的 python 类中

    我有一个 python 项目 它使用 google protobufs 作为通过网络进行通信的消息格式 使用以下命令可以直接从 proto 文件生成 python 文件protoc程序 我该如何配置我的setup py项目文件 以便它自动调