【问题标题】:Inter-function communication between calling and called functions调用函数和被调用函数之间的函数间通信
【发布时间】:2016-01-01 20:00:12
【问题描述】:

我想知道是否有一种干净的方法可以在调用函数/方法和被调用函数/方法之间建立某种通信。比如说,调用者是主驱动程序的一部分,它在 UI 上显示当前应用程序状态。它需要连接到远程网络节点,为此它调用驻留在另一个 Python 模块中的另一个方法(在同一个线程中)。

主(驱动)模块:

import ssh_client

node_ip = "10.10.10.10"
node_user = "myuser"
node_pass = "mypass"
conn_result = False

while not conn_result :
    conn_result = ssh_client.connect(node_ip, node_user, node_pass)

    # process custom return codes from connect method here...

ssh_client 模块:

import paramiko

def connect(node_ip, node_user, node_pass):
    retries_left = 3

    while retries_left > 0:
        try:
            paramiko.SSHClient().connect(node_ip, username=node_user, password=node_pass)
            return True
        except Exception:
            retries_left -= 1

    return False

现在,网络模块方法在尝试连接时,可能会遇到网络延迟或其他问题导致的各种问题,并会相应地重试连接。此时,我希望该方法以某种方式通知我的主调用方方法连接失败并且正在尝试重新连接。

在上面的例子中,我是根据返回码来获取当前的连接情况。但是,我不依赖返回码,而是希望在连接方法执行时 的数据。换句话说,当出现异常时,我希望 connect 方法告诉驱动模块告诉驱动模块出现异常并尝试重新连接。

虽然可以通过粗略的方法来实现这一点,例如将状态更新到文本文件并让调用者轮询它以了解状态变化,但这听起来并不是一个非常有说服力的解决方案。 Python中有什么东西可以在这里证明很方便,我是否遗漏了一些明显的东西?解决这个问题的好方法是什么?

【问题讨论】:

  • 是否让调用者负责重试连接是一种选择?这对我来说似乎是更清洁的解决方案。 connect 然后只会让异常冒泡给调用者。
  • 很遗憾,不,我希望网络模块负责所有重新连接,让调用者只负责调用任务。
  • 不幸的是,你不能像你计划的那样去做,尤其是不能在一个线程中。任何类型的信息都被发送到堆栈中,直到接收者再次位于堆栈顶部才被处理。这意味着被调用的函数必须首先返回(或以任何方式终止)。堆栈中不同位置的两个函数不能同时运行代码。
  • 如果您的调用者应对通知做出反应,您必须在单独的线程或进程中异步调用 connect
  • 另一种可能是使用异步框架。有一些,只有两个名称:asyncio 和 Twisted。

标签: python function methods communication messaging


【解决方案1】:

一个非常幼稚的方法是这样的:

from threading import Thread
from Queue import Queue

def connect(queue, *args):
    retries_left = 3

    while retries_left > 0:
        try:
            your_connect_call(*args)
        except Exception:
            queue.put('Error')
            retries_left -= 1

    # Send poison pill to notify the caller that the task is complete
    queue.put(None)
    return False

def caller():
    q = Queue()
    t = Thread(target=connect, args=(q,))
    t.start()
    while True:
        msg = q.get()
        if msg is None:
            break
        print(msg)
    res = t.join()
    return res

调用者启动一个单独的线程并将Queue 传递给被调用的方法。被调用的方法使用状态通知填充Queue,调用者可以对其做出反应(这里它只是打印这些消息)。被调用的方法通过发送None 信号通知调用者不再有消息。调用者等待该信号,然后等待方法返回。

【讨论】:

  • 这绝对可行,但我真的很期待在不涉及线程的情况下这样做。无论如何都会尝试一下,谢谢。
猜你喜欢
  • 2016-04-06
  • 1970-01-01
  • 1970-01-01
  • 2011-07-01
  • 1970-01-01
  • 2021-08-21
  • 1970-01-01
  • 2023-03-12
  • 1970-01-01
相关资源
最近更新 更多