3

我如何要求docker-py事件停止events流迭代?例如,我想停下来观看码头工人的活动。

from docker import Client


client = Client(base_url='unix://var/run/docker.sock')
events = client.events(decode=True)

for event in events:
    print(event)

print('exited')

client.events()返回生成器在这里构建。

4

2 回答 2

2

生成器client.events()阻塞了 unix 套接字recv调用。如果您不能等到下一个事件并break退出循环,那么您需要中断套接字。

不幸的是,我找不到通过 docker-py 执行此操作的干净方法。我发现的唯一方法需要使用/覆盖私有方法,这当然是脆弱的。如果您正在寻找一个强大的解决方案,我建议您直接进行 api 调用,然后您可以自由地在套接字上设置自己的超时时间或在非阻塞模式下使用它。

话虽如此,要直接回答这个问题,这里有一种修补Client类的方法,以将 api 响应作为属性添加到由events().

from docker import Client

class CustomGenerator(object):
    def __init__(self, stream, response, decode):
        self.stream = stream
        self.response = response
        self.decode = decode

    def __iter__(self):
        for item in super(CustomClient, self.stream).\
                _stream_helper(self.response, self.decode):
            yield item

class CustomClient(Client):
    def _stream_helper(self, response, decode=False):
        return CustomGenerator(self, response, decode)

得到响应后,您可以关闭套接字,这将在生成器中引发异常。在这个例子中,我使用一个线程在 5 秒后停止监听。

from threading import Timer
import requests
import socket

client = CustomClient(base_url="unix://var/run/docker.sock")
events = client.events()

def listen_for_events():
    print("listening")

    try:
        for event in events:
            print(event)
    except requests.packages.urllib3.exceptions.ProtocolError:
        pass

    print("done listening")

def stop_listening():
    sock = client._get_raw_response_socket(events.response)
    sock.shutdown(socket.SHUT_RDWR)

Timer(5, stop_listening).start()

listen_for_events()
于 2016-04-09T01:27:30.693 回答
0

为了能够中断等待下一个事件,您可以通过在两秒时间范围内侦听事件来使用方法的since参数untilevents()

from datetime import datetime, timedelta

import docker
client = docker.from_env()

delta = timedelta(seconds=2)
since = datetime.utcnow()
until = datetime.utcnow() + delta
while True:
    for event in client.events(since=since, until=until, decode=True):
        print(event)
    since = until
    until = datetime.utcnow() + delta

由于您等待事件 2 秒,因此您的执行线程将被阻塞最多 2 秒。因此,如果用户点击Ctrl+C,脚本将很快终止。

于 2017-04-24T21:33:31.807 回答