简体   繁体   English

Python-扭曲的主循环内的while循环?

[英]Python - while loop inside twisted main loop?

I need to know if its possible to run a while loop inside a twisted websocket main loop 我需要知道是否有可能在扭曲的websocket主循环中运行while循环

the while loop im referring to is the lib you see in this question: shout-python segmentation fault how can I fix this? 我所指的while循环是您在此问题中看到的lib: shout-python segmentation fault我该如何解决?

all I need it to do is send the new title once it updates, though I can handle that part. 我需要做的就是在更新后发送新标题,尽管我可以处理。 Its that while self.running: in the play() function. while self.running:play()函数中。 If you can help I'll surely appreciate it. 如果您能提供帮助,我将不胜感激。

For Twisted's single-threaded, cooperative multitasking system to operate at its best, it's important that any particular piece of code running in the reactor thread not run for too long without giving control back to the reactor. 为了使Twisted的单线程协作多任务系统以最佳状态运行,重要的是,在反应堆线程中运行的任何特定代码段都不能运行太长时间而不将控制权交还给反应堆。 As long as any one piece of code is running in that thread, no other code is running in that thread. 只要在该线程中运行任何代码,就不会在该线程中运行其他代码。 In a single-threaded, cooperative multitasking system that means other events aren't being serviced. 在单线程,协作式多任务处理系统中,这意味着不处理其他事件。

Depending on your application, it may be fine for a single piece of code to run without giving up control for many milliseconds, many seconds, perhaps even minutes. 根据您的应用程序,运行一段代码而无需花费很多毫秒,几秒钟甚至几分钟的时间来放弃控制可能会很好。 It's entirely dependent on what events your application is responsible for handling and what level of responsiveness you want to get from it. 这完全取决于您的应用程序负责处理哪些事件以及您希望从中获得什么级别的响应性。 When writing general purpose library code for a system like this, most people assume that it's only okay to run code for a single task for a handful of milliseconds or so before giving up control - to err on the side of being suitable for use in more applications rather than fewer (although people rarely consider the exact time limit, mostly operations are separated into "pretty quick" and everything else). 当为这样的系统编写通用库代码时,大多数人认为在放弃控制之前为单个任务运行代码几毫秒左右是可以的-出于适合更多用途而出错应用程序而不是更少的应用程序(尽管人们很少考虑确切的时间限制,但大多数操作被分为“相当快”和其他所有内容)。

What's almost always unacceptable is to run a single piece of code indefinitely without giving control back to the reactor. 几乎总是不能接受的是无限期地运行单个代码而没有将控制权交还给反应堆。 The loop in the answer you linked to is effectively infinite and so it will hold control for an arbitrarily long period of time (perhaps for most of the runtime of the program). 您链接到的答案中的循环实际上是无限的,因此它将控制任意长时间(可能在程序的大部分运行时)。 There are few if any applications that can tolerate this since the result is that other events will never be handled. 几乎没有应用程序可以容忍这种情况,因为结果是永远不会处理其他事件。 If it's tolerable for your application to be unable to respond to any events while it spends its entire run time working on a single task then you may not need a multitasking system at all (ie, you may not need Twisted, you may be able to just use a while loop). 如果您的应用程序在整个运行时间都花在单个任务上的情况下无法响应任何事件,那么您可能根本不需要多任务系统(即,您可能不需要Twisted,则可以只需使用while循环)。

The loop in that answer is basically a "process some data as quickly as possible" loop. 该答案中的循环基本上是“尽快处理某些数据”循环。 There are a few options for implementations of this kind of work in ways that are more multitasking-friendly. 对于这种工作,有一些选择更易于执行多任务处理。

One way is a literal translation of the loop into a pattern that's friendly to the reactor. 一种方法是将循环从字面上转换为对反应堆友好的模式。 You can do this with a generator: 您可以使用生成器执行此操作:

from twisted.internet.task import cooperate

class Audio(object):
    def play(self):
        # ... setup stuff ...
        while self.running:
            # ... one chunk of work ...
            yield

def main():
    ...
    cooperate(Audio().play())

cooperate takes an iterator and iterates over it - but not all at once. cooperate需要一个迭代器并对其进行迭代-但并非一次完成。 It iterates it a few times and then gives up control to the reactor. 迭代几次,然后放弃对反应器的控制。 Then it iterates it a few more times and then gives up control again. 然后将其迭代几次,然后再次放弃控制。 This continues until the iterator is exhausted (or the reactor is stopped). 这一直持续到迭代器耗尽(或反应器停止)为止。

Another slightly less literal translation is based on LoopingCall which takes over responsibility for the looping construct, leaving you only to supply the body of the loop: 另一个稍微少一点的文字转换是基于LoopingCall ,它负责循环的构造,而您只需要提供循环的主体即可:

from twisted.internet.task import LoopingCall

class Audio(object):
    def play(self):
        # ... setup stuff ...

        LoopingCall(self._play_iteration).start(0)

    def _play_iteration(self):
        # ... one chunk of work

This gives you control over the rate at which the loop iterates. 这使您可以控制循环的迭代速率。 The 0 passed to start in this example means "as fast as possible" (wait 0 seconds between iterations) - while remaining cooperative with the rest of the system. 在此示例中,传递给start0表示“尽可能快”(在两次迭代之间等待0秒)-同时保持与系统其余部分的协作。 If you wanted one iteration per second, you would pass 1 , etc. 如果您想每秒进行一次迭代,则可以传递1 ,依此类推。

Another less literal option is to use a data flow abstraction - for example, Twisted's native producer/consumer system or the newer tubes library - to set up multitasking-friendly data processing pipelines that are further abstraction from the specific "read, process" loop in the linked answer. 另一个不太实际的选择是使用数据流抽象(例如Twisted的本机生产者/消费者系统或较新的Tubes库)来建立多任务友好的数据处理管道,这些管道从特定的“读取,处理”循环中进一步提取。链接的答案。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM