在Python中访问全局队列对象

3
我正在用Python构建一个与Twitter交互的消息应用程序。我想创建一个全局FIFO队列,以便twitterConnection对象可以访问并插入新消息。
这是应用程序的主要部分:
    #!/usr/bin/python

    from twitterConnector import TwitterConnector
    from Queue import deque

    #instantiate the request queue
    requestQueue = deque()

    #instantiate the twitter connector
    twitterInterface = TwitterConnector()

    #Get all new mentions
    twitterInterface.GetMentions()

具体来说,我希望能够调用TwitterConnector类的.GetMentions()方法,并处理任何新提及,并将这些消息放入队列以进行单独处理。
以下是目前的TwitterConnector类:
class TwitterConnector:
   def __init__(self):
      self.connection = twitter.Api(consumer_key=self.consumer_key,consumer_secret=self.consumer_secret,access_token_key=self.access_token_key,access_token_secret=self.access_token_secret)
      self.mentions_since_id = None

   def VerifyCredentials(self):
      print self.connection.VerifyCredentials()

   def GetMentions(self):
      mentions = self.connection.GetMentions(since_id=self.mentions_since_id)
      for mention in mentions:
         print mention.text
         global requestQueue.add(mention)  # <- error  

任何帮助都将不胜感激。
更新:让我看看是否可以更清楚地阐明用例。我的TwitterConnector旨在检索消息,并最终将twitter状态对象转换为包含下游处理所需信息的简化对象。在同一方法中,它将执行一些其他计算,以尝试确定其他所需信息。实际上,我想将转换后的对象放入队列中。作为一个简化的示例,此方法将将twitter状态对象映射到一个新对象中,该对象将包含属性,例如:原始网络(twitter)、用户名、消息和位置(如果可用)。然后将此新对象放入队列中。
最终,将有其他连接器用于其他消息系统,它们将执行类似的操作。它们将接收消息填充新消息对象并将其放入相同的队列以进行进一步处理。一旦消息完全处理完毕,则会制定响应,然后将其添加到适当的队列以进行传输。使用上述新对象,一旦对推文内容的实际处理完成,那么基于原始网络和用户名,可能会通过twitter向发起人返回响应。

我曾考虑在构造函数中传递队列的引用(或作为方法的参数),我也考虑过修改方法以返回新对象的列表并迭代它们以将它们放入队列中,但我想确保没有更好或更有效的方式来处理这个问题。我还希望能够对日志对象和数据库处理程序执行相同的操作。你有什么想法吗?


你得到了什么错误? - jsalonen
我要问一个显而易见的问题:为什么你要定义自己的 TwitterConnector,而不是使用现有的 Python API 呢? - jsalonen
1
对于强大的共享队列,您可能希望使用AMQP。看看Celery。 - Paulo Scardine
我建议将所有这些队列输入点都派生自同一个基类,该基类具有一个“add_to_queue”方法和一个接收队列对象的构造函数。 - idanzalz
2个回答

4
问题在于“global”应该单独成行。
global requestQueue
requestQueue.add(mention)

此外,requestQueue必须出现在定义类的模块中。如果您从另一个类导入requestQueue符号,则根本不需要全局变量。
from some_module import requestQueue
class A(object):
    def foo(o):
         requestQueue.add(o) # Should work

同意。从语法层面上来说,这是一个有效的解决方案,但它并不能解决设计问题。 - jsalonen
5
我的哲学是先回答问题,再告诉他为什么这个问题不正确。 - idanzalz

2
一般来说,避免使用全局变量是一个好主意;通常存在更好的设计。关于全局变量问题的详细信息,请参见例如([1], [2], [3], [4])。
如果您想通过使用全局变量在多个TwitterConnector实例之间共享单个requestQueue,您还可以在其构造函数中将队列传递给连接器。
class TwitterConnector:
   def __init__(self, requestQueue):
      self.requestQueue = requestQueue
      ...

   def GetMentions(self):
      mentions = self.connection.GetMentions(since_id = self.mentions_since_id)
      requestQueue = deque()
      for mention in mentions:
         print mention.text
         self.requestQueue.add(mention)

相应地,您需要将requestQueue提供给构造函数,如下所示:
twitterInterface = TwitterConnector(requestQueue)

1
我同意不使用全局变量,但单例仍然是一个非常有效的模式。只需要在不同的模块上定义它们,以便可以作为符号导入。 - idanzalz
你假设每次调用 GetMentions 都可能返回不同的队列,而且它们不需要随时间聚合。这是与他尝试做的主要功能差异。 - idanzalz
一个有道理的观点。重构过了。我也同意单例模式没有什么问题,但我不明白为什么要在这里使用这种模式(我们为什么要让 twitterConnector 依赖于使用它的特定应用程序呢?)。 - jsalonen
1
如果这不是TwitterConnector的一个组成部分,那么也许正确的做法是将其作为参数传递给GetMentions方法。但实际上我们需要更深入地了解其目的。他已经在使用连接的API,所以也许TwitterConnecter只是一个不好的名称。 - idanzalz
我完全同意你的看法。有了这些信息,我们只能向他提供一些技巧。 - jsalonen

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接