【问题标题】:Why is merging Python system classes with custom classes less desirable than hooking the import mechanism?为什么将 Python 系统类与自定义类合并不如挂钩导入机制?
【发布时间】:2014-07-09 02:18:13
【问题描述】:

我正在开发一个项目,旨在通过部分排序信息来增加 Python 套接字消息。我正在构建的库是用 Python 编写的,需要插入到现有系统通过套接字函数发送的消息中。

我已经阅读了一些资源,即@Omnifarious 对这个问题python-importing-from-builtin-library-when-module-with-same-name-exist的回答

有一件你可以做的极其丑陋和可怕的事情 涉及挂钩导入机制。这是你应该做的 可能不会,但它可能会起作用。它转动你的日历 模块成为系统日历模块和您的日历的混合体 模块。

我已经实现了导入机制解决方案,但我们决定这不是我们想要采取的方向,因为它过于依赖环境。在我看来,将类合并到混合中而不是依赖于导入机制的解决方案似乎是最好的方法。

为什么混合动力被称为丑陋可怕的解决方案?我想开始在我的项目中实施它,但我对这些警告持谨慎态度。看起来确实有点骇人听闻,但由于它是安装脚本的一部分,运行一次不就OK了吗?

这是一个代码sn-p,其中插入需要在发送套接字消息之前拦截它:

class vector_clock:

  def __init__(self):
   """
   Initiate the clock with the object
   """
   self.clock = [0,0]

  def sendMessage(self):
   """
   Send Message to the server
   """
   self.msg = "This is the test message to that will be interposed on"
   self.vector_clock.increment(0) # We are clock position 0

   # Some extraneous formatting details removed for brevity….
   # connectAndSend needs interpositioning to include the vector clock

   self.client.connectAndSend(totalMsg);
   self.client.s.close()

【问题讨论】:

  • 请强调问题是什么。我猜你收到了反对票,因为不清楚你在问什么。
  • @kapa 非常感谢您的建议!我将进行编辑以使其更清晰。
  • 标题听起来像是在拖钓,而不是引用:/
  • 现在好多了,原来的问题也解决了:到处都可以评论:)。
  • 你看过猴子补丁套接字吗,gevent (gevent.org/intro.html#monkey-patching) 的做法?我不确定这是否是您所说的“合并”的意思,但是 gevent 人员在一个很多人使用的项目中非常成功地使用了这种方法。

标签: python sockets networking distributed-system


【解决方案1】:

根据我对您帖子的理解,您希望修改现有的套接字库以将您自己的功能注入其中。

是的,这是完全可行的,甚至可能是解决您的问题的最简单的方法,但您必须考虑您所做的一切可能带来的影响。

最重要的一点是,您不仅要修改自己的套接字,还要修改在进程的任何部分中运行的任何使用套接字库的东西,除非它使用自己的类加载器。我知道您可能正在使用一些现有的库,它使用套接字并且您想将此功能注入其中,但这会影响一切。

从这里您必须考虑一个问题:您的更改是否 100% 向后兼容。除非你能保证你知道你的进程使用的任何库所使用的套接字的每一个用例(提示:你不能),否则你需要确保它完全保留所有现有功能或某些核心库中的其他东西会神秘地破坏,您将不知道为什么也无法调试它。 100% 向后兼容(或尽可能接近)的一个例子是注入一个装饰器,它将时间信息保存到您自己的模块之一。

如果您完全理解这一点并且仍然认为您的解决方案是一个好的解决方案,那么我会说“去做吧”。但是,您是否考虑过任何替代方案?

如果您只需要为您使用的一组特定库注入此功能,那么我建议您执行修补之类的操作:https://docs.python.org/3/library/unittest.mock.html#unittest.mock.patch

您可以对要修改的任何核心库进行子类化,然后修补该库以改用您的类。补丁的核心是修改目标模块中使用的全局绑定,以使用与其最初使用的不同的类/模块。

PS。我不认为你的情况需要挂钩导入机制。

【讨论】:

  • 我的矢量时间戳库中的 init.py 文件使用 patcher = mock.patch('__main__.socket.socket', SVSocket.SVSocket) 调用静态函数。一个棘手的问题是停止补丁,以便我可以在装饰器 SVSocket 类中创建一个普通的 socket.socket 变量。为此,我使用了mock.patch.stopall()。正在进行中的工作,但如果有用的话,完整的代码就在这里bitbucket.org/bestchai/shivector/src/default/python
  • mock.patch.stopall() 有问题bugs.python.org/issue21239。一个固定版本的 mock.py 包含在我在 Python 版本 中成功使用的链接中
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2014-10-18
  • 2019-05-03
  • 2022-12-22
  • 1970-01-01
  • 2021-04-27
  • 2015-07-30
  • 1970-01-01
相关资源
最近更新 更多