如何在某个特定时间退出发电机?

时间:2016-11-11 09:17:48

标签: python generator

我正在阅读Twitter Streaming API中的推文。连接到API后,我得到了一台发电机。

我在收到的每条推文中循环,但我想退出迭代器,比如说,在18PM。收到每条推文后,我会检查它是否晚于指定的时间戳并停止。

问题是我没有经常收到推文。所以,我可以在17:50收到一个,下一个在晚上19点收到。那时我才发现时间已经过去,我需要停下来。

有没有办法在下午18点强制停止?

这是我的代码的高级视图:

def getStream(tweet_iter):
    for tweet in tweet_iter:
        #do stuff
        if time_has_passed():
            return

tweet_iter = ConnectAndGetStream()
getStream(tweet_iter)

3 个答案:

答案 0 :(得分:1)

通过将设计功能分成两个独立的流程,可以解决您的问题:

  1. 作为Twitter API和
  2. 包装的推特流程
  3. 当达到退出时间时能够终止twitter进程的监视进程。
  4. 以下代码使用Python的多处理模块原型化上述功能:

    import multiprocessing as mp
    import time
    
    EXIT_TIME = '12:21' #'18:00'
    
    def twitter():
    
        while True:
            print 'Twittttttttttt.....'
            time.sleep(5)
    
    def get_time():
    
        return time.ctime().split()[3][:5]
    
    if __name__ == '__main__':
    
        # Execute the function as a process
        p = mp.Process( target=twitter, args=() )
        p.start()
    
        # Monitoring the process p
        while True:
            print 'Checking the hour...'
            if get_time() == EXIT_TIME:
                p.terminate()
                print 'Current time:', time.ctime()
                print 'twitter process has benn terminated...'
                break
            time.sleep(5)
    

    当然,您可以使用 p.join(TIMEOUT),而不是使用我的示例中显示的while True循环作为指向here

答案 1 :(得分:1)

以下是使用线程和python调度程序的示例:

import threading
import time
import os
import schedule

def theKillingJob():
    print("Kenny and Cartman die!")
    os._exit(1)

schedule.every().day.at("18:00").do(theKillingJob,'It is 18:00')

def getStream(tweet_iter):
    for tweet in tweet_iter:
        #do stuff

def kenny():
    while True:
        print("Kenny alive..")
        schedule.run_pending()
        time.sleep(1)

def cartman():
    while True:
        print("Cartman alive..")

        tweet_iter = ConnectAndGetStream()
        getStream(tweet_iter)

        # You can change whenever you want to check for tweets by changing sleep time here
        time.sleep(1)

if __name__ == '__main__':
    daemon_kenny = threading.Thread(name='kenny', target=kenny)
    daemon_cartman = threading.Thread(name='cartman', target=cartman)
    daemon_kenny.setDaemon(True)
    daemon_cartman.setDaemon(True)

    daemon_kenny.start()
    daemon_cartman.start()
    daemon_kenny.join()
    daemon_cartman.join()

答案 2 :(得分:1)

为生产者创建一个单独的线程,并使用Queue进行通信。我还必须使用threading.Event来阻止制作人。

import itertools, queue, threading, time

END_TIME = time.time() + 5  # run for ~5 seconds

def time_left():
    return END_TIME - time.time()

def ConnectAndGetStream():             # stub for the real thing
    for i in itertools.count():
        time.sleep(1)
        yield "tweet {}".format(i)

def producer(tweets_queue, the_end):   # producer
    it = ConnectAndGetStream()
    while not the_end.is_set():
        tweets_queue.put(next(it))

def getStream(tweets_queue, the_end):  # consumer
    try:
        while True:
            tweet = tweets_queue.get(timeout=time_left())
            print('Got', tweet)
    except queue.Empty:
        print('THE END')
        the_end.set()

tweets_queue = queue.Queue()  # you might wanna use the maxsize parameter
the_end = threading.Event()
producer_thread = threading.Thread(target=producer,
                                   args=(tweets_queue, the_end))
producer_thread.start()
getStream(tweets_queue, the_end)
producer_thread.join()