【问题标题】:python irc bot trying to consume two different messaging systempython irc bot试图使用两个不同的消息系统
【发布时间】:2020-10-06 20:22:36
【问题描述】:

我正在使用 python irc 模块 [1] 和 python 中的 pika 模块来创建一个 irc 机器人,它同时监听通道消息和 rabbitmq 队列。

我从 [2] 中获取源代码并将鼠兔元素添加到其中:

#! /usr/bin/env python
#
# Example program using irc.client.
#
# This program is free without restrictions; do anything you like with
# it.
#
# Joel Rosdahl <joel@rosdahl.net>

import sys
import argparse
import itertools

import irc.client
import pika


target = "#test"
"The nick or channel to which to send messages"


def on_connect(connection, event):
  if irc.client.is_channel(target):
      connection.join(target)
      return
  main_loop(connection)


def on_join(connection, event):
  main_loop(connection)


def get_lines():
  while True:
      yield sys.stdin.readline().strip()


def main_loop(connection):
  for line in itertools.takewhile(bool, get_lines()):
      print(line)
      connection.privmsg(target, line)
  connection.quit("Using irc.client.py")


def on_disconnect(connection, event):
  raise SystemExit()


def get_args():
  parser = argparse.ArgumentParser()
  parser.add_argument('server')
  parser.add_argument('nickname')
  parser.add_argument('target', help="a nickname or channel")
  parser.add_argument('-p', '--port', default=6667, type=int)
  jaraco.logging.add_arguments(parser)
  return parser.parse_args()


def callback(ch, method, properties, body):
  print(" [x] Received %r" % body)


def get_channel():
  creds = pika.PlainCredentials('testuser', 'testing')

  params = pika.ConnectionParameters(
      host="localhost",
      virtual_host="/test",
      credentials=creds)

  connection = pika.BlockingConnection(params)
  channel = connection.channel()

  channel.queue_declare(queue='test')

  channel.basic_consume(
      queue='test', on_message_callback=callback, auto_ack=True)

  return channel


def main():
  chan = get_channel()

  reactor = irc.client.Reactor()
  try:
      c = reactor.server().connect("irc.local", 6667, "testuser")
  except irc.client.ServerConnectionError:
      print(sys.exc_info()[1])
      raise SystemExit(1)

  c.add_global_handler("welcome", on_connect)
  c.add_global_handler("join", on_join)
  c.add_global_handler("disconnect", on_disconnect)

  print("Processing reactor")
  reactor.process_forever()
  print("Channel : start consuming")
  channel.start_consuming()


if __name__ == '__main__':
  main()

上面代码的问题是我没有将get_lines()代码修改为实际 从消息队列中获取,因为我不知道要更改它的目的。

此外,“reactor.process_forever()”行会阻塞“channel.start_sumption()”行,并且 显然,如果我将 channel.start_sumption() 移到 reactor.process_forever() 上方, reactor.process_forever() 没有运行。

在这一点上,我很难过。我考虑过使用多处理线程;但我的 线程经验为零,即使在阅读 [3] 之后,我也不完全确定 这会有所帮助。老实说,这让我有点困惑。

我想添加一个 on_* 回调处理程序,但因为这些事件是 所有基于 irc 的处理程序都不会监听 rabbitmq 队列。

可能有人对如何同时运行 process_forever() 提出建议 循环和 start_sumption() 循环;也就是说,让机器人 监听 irc 频道和消息队列?

谢谢!

:ed

[1] - https://github.com/jaraco/irc

[2] - https://github.com/jaraco/irc/blob/master/scripts/irccat.py

[3] - https://realpython.com/intro-to-python-threading/

【问题讨论】:

  • 有时模块具有其他功能来构建自己的循环并添加来自其他模块的功能 - 这样一个循环可以替换两个循环 - 也许您应该阅读两个模块的文档以查看是否有示例如何创建自己的循环。
  • 似乎 irc 有process_once,你可以在正常的while-loop 中运行。如果你发现 pika 有类似的东西,那么你可以在一个 while-loop 中运行它们,它们将同时工作,无需线程或多处理。
  • start_consuming的源代码中可以看到while-loop。也许如果您使用此代码而不是 start_consuming 并输入 reactor.process_once() in while-loop from start_sumption` 那么也许所有代码都可以同时工作。
  • @furas,在阅读您的评论之前,我尝试每秒使用 irc 模块的调度程序的 execute_every() 并调用一个函数。它不完全是“实时的”,但大致足够接近。也就是说,我认为您的“将所有内容放在一段时间内”似乎比 1 秒调度程序更好,而且可能更实时。谢谢!

标签: python rabbitmq irc


【解决方案1】:

感谢@fura(非常荣幸!)帮助澄清我能做什么。最终的工作结果代码如下:

#! /usr/bin/env python
#
# Example program using irc.client.
#
# This program is free without restrictions; do anything you like with
# it.
#
# Joel Rosdahl <joel@rosdahl.net>

import sys
import argparse
import itertools

import irc.client
import pika


target = "#test"
"The nick or channel to which to send messages"


def on_connect(connection, event):
    if irc.client.is_channel(target):
        connection.join(target)
        return


def on_disconnect(connection, event):
    raise SystemExit()


def get_channel():
    creds = pika.PlainCredentials('testuser', 'testing')

    params = pika.ConnectionParameters(
        host="msg.local",
        virtual_host="/test",
        credentials=creds)

    connection = pika.BlockingConnection(params)
    channel = connection.channel()

    channel.queue_declare(queue='test')

    return channel


def main():
    chan = get_channel()

    reactor = irc.client.Reactor()
    try:
        print("connect to server")
        c = reactor.server().connect("irc.local", 6667, "testUser")
    except irc.client.ServerConnectionError:
        print(sys.exc_info()[1])
        raise SystemExit(1)

    c.add_global_handler("welcome", on_connect)
    c.add_global_handler("disconnect", on_disconnect)

    print("Processing reactor")
    while True:
        reactor.process_once()
        mf, hdr, bd = chan.basic_get("test")
        if mf:
            chan.basic_ack(mf.delivery_tag)
            bdd = bd.decode('utf-8')
            if "cmd:" in bdd:
                p = bdd.replace("cmd:", "").strip()
                if p.lower() == "quit":
                    c.quit("Buckeroo Banzai!")
                else:
                    c.privmsg("#test", bdd)
            else:
                c.privmsg("#test", bdd)


if __name__ == '__main__':
    main()

当然,我用短信测试过这个。。没有通过它发送一个巨大的文本文件,所以不确定它是否有效或浪费资源。需要将其付诸实践,看看它是否会窒息。

再次感谢@fura,感谢您的帮助和建议!

:埃德

【讨论】:

    猜你喜欢
    • 2012-06-05
    • 2011-05-12
    • 1970-01-01
    • 2017-02-25
    • 1970-01-01
    • 2014-01-12
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多