停止 docker-py 事件流迭代
Stop docker-py events stream iteration
我如何请求 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()
return 生成器构建 here。
client.events()
生成器正在阻塞 unix 套接字 recv
调用。如果您不能等到下一个事件并且 break
退出循环,则需要中断套接字。
不幸的是,我找不到通过 docker-py 执行此操作的干净方法。我发现的唯一方法需要 using/overriding 私有方法,这当然很脆弱。如果您正在寻找一个可靠的解决方案,我建议您直接进行 api 调用,然后您可以自由地在套接字上设置自己的超时或在非阻塞模式下使用它。
话虽这么说,要直接回答这个问题,这里有一种方法可以修补 Client
class 以将 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()
为了能够中断等待下一个事件,您可以使用 events()
方法的 since
和 until
参数,通过在两秒的时间范围内监听事件。
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
,脚本将很快终止。
我如何请求 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()
return 生成器构建 here。
client.events()
生成器正在阻塞 unix 套接字 recv
调用。如果您不能等到下一个事件并且 break
退出循环,则需要中断套接字。
不幸的是,我找不到通过 docker-py 执行此操作的干净方法。我发现的唯一方法需要 using/overriding 私有方法,这当然很脆弱。如果您正在寻找一个可靠的解决方案,我建议您直接进行 api 调用,然后您可以自由地在套接字上设置自己的超时或在非阻塞模式下使用它。
话虽这么说,要直接回答这个问题,这里有一种方法可以修补 Client
class 以将 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()
为了能够中断等待下一个事件,您可以使用 events()
方法的 since
和 until
参数,通过在两秒的时间范围内监听事件。
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
,脚本将很快终止。