While循环中的Python异步请求

时间:2018-04-19 18:53:04

标签: python multithreading asynchronous python-requests zeromq

我目前有一个程序使用while循环来接收来自 zmq_socket 的订阅者的邮件。每次收到新消息时,我都需要向服务器发出HTTP请求,然后服务器会发送响应。此调用大约需要1秒钟。我想有办法调用HTTP请求,然后再次循环,从zmq_socket获取另一条消息,并在不等待第一个HTTP请求的情况下调用另一个HTTP请求。

伪代码看起来像这样:

url = 'http://example.com'

def callback(message):
    r = requests.post(url, data = message)
    # store r in class variable (not sure how to do this asynchronously) 

while True:
    message = zmq_socket.recv_json()
    callback(message)
    # do other stuff
    # continue without waiting for callback to finish

有没有办法在Python中执行此操作?

我已经查看了tornadoasyncio这样的图书馆以及查看multithreading并且我还没有找到解决方案。

1 个答案:

答案 0 :(得分:0)

是的,有几种方法可以在Python中执行此操作:

它们的主要区别在于操作成本和性能。

A)
最简单和最便宜的是使用独立的 .mainloop() - 协调处理的Tkinter本地基础设施,其中独立的串行处理以协同的方式廉价地进行,具有额外的软实际如果有人愿意使用它们,可以获得时间利益。有了这个选项,我们可以使用 callback 甚至 .after() .after_idle() 进行软安排>(因为您的代码经常进入.recv()接收器的阻塞模式)调度方法。

B)
另一种更智能的Tkinter原生基础设施工具可以更有效地完成类似的工作,因为 message 实际上会成为Tkinter的 StringVar -instance,已配备<aVarTRACER>:<aTracedVarEventHANDLER> - 监控工具。这样, message 的任何值更改都会自动触发 callback ,而代码不会采取任何进一步的步骤(但正确的设置这样的StringVar监视器)。我喜欢这款Tkinter工具,确实适用于许多强大的Live-GUI设计。

 ##########
 # THEORY :
 # .trace_variable( <mode>, <aTracedVarEventHANDLER> )
 #                  <mode> := { "w": WRITE-DELTA-TRACER    |
 #                              "r": READ-ACCESS-TRACER    |
 #                              "u": UNDEFINE-DELETE-TRACER
 #                               }

 #########
 # SETUP :
 pass;             aMessageVAR = StringVar()
 id_W            = aMessageVAR.trace_variable( "w", \ 
 onWriteChange_var_aMessageVAR ) #             "WRITE"-DELTA-Event <~ callback()
 # + any change of aMessageVAR auto-triggers  onWriteChange_var_aMessageVAR()
 #                                             with 3 params:
 #                                                  aTkNameOfVAR,
 #                                                  aTkArrayIndex,
 #                                                  aTkAccessMode {"w"|"r"|"u"}
 #
 #                                             global       aMessageVAR
 #                                             aLocalCopy = aMessageVAR.get()
 #                                             #LocalCopy content b4 next .set()

 ############
 # ORIGINAL :
 #____________________________________________ original while-loop:
 while True:
                   aMessageVAR.set( zmq_socket.recv_json() )
                   #                                     ^__blocks, better
                   #                                        design
                   #                                        non-blocking .poll()
                   #                                        scheduled with
                   #                                        .after( nMS, aPoll )
                   #                                        + .set() on POSACK'd
 #########
 # FINALLY:
 pass;             aMessageVAR.trace_vdelete( "w", id_W ) # CLEAN THE TRACER

C)
最后,但并非最不重要的是,可以从 while -loop内部设计可扩展的性能ZeroMQ工作流,其中任何此类收到的message被编组到远程池中 - 另一个zmq_task_to_pool_of_workers_socket的工人。这种方法可以轻松地帮助掩盖&#34;除了获得异步.post() - 方法和其他相关工作的基本技巧外,还有更多的远程工作者添加到工作池中的工作者处理延迟#34;外部&#34;所述while - 循环。此选项的几乎线性性能扩展+延迟屏蔽可能超出共享GIL锁定步进,因此如果这些是核心设计功能,则可以采用此方法。