在Python中,当线程在上下文管理器中启动时会发生什么?

问题描述 投票:0回答:1

作为一个简单的例子,以一个基本的套接字为例:

import socket
import threading
import time

def stream(message, socket_):
    while True:
        socket_.sendall(message)
        time.sleep(1)

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as sock:
    sock.connect((address, port))
    threading.Thread(target=stream, args=("hello world!", sock), daemon=True)

我假设流程是这样的:

  1. 输入上下文,创建袜子。
  2. 创建线程并使用 sock 调用流。
  3. 上下文退出,sock 关闭。
  4. 流线程未使用关闭的套接字,可能会崩溃。

是吗?如果是这样,有没有办法在一个或多个单独的线程中继续上下文?

python multithreading sockets python-multithreading contextmanager
1个回答
0
投票

是的,你是对的。在您提供的代码中,当退出 with 块时,sock套接字对象将被关闭。因此,如果 stream 线程在关闭后继续使用 sock 对象,则会引发 socket.errorsocket.timeout 异常。

为了避免此问题,您可以在 with 块外部创建套接字,并将其作为参数传递给 stream 函数。这样,当退出with块时,套接字不会被关闭,stream函数可以继续使用它。

这是代码的更新版本,可以避免过早关闭套接字:

import socket
import threading
import time

def stream(message, socket_):
    while True:
        socket_.sendall(message)
        time.sleep(1)

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
sock.connect((address, port))

thread = threading.Thread(target=stream, args=("hello world!", sock), daemon=True)
thread.start()

在此代码中,sock套接字对象是在with块之外创建的。然后,使用 sock 对象作为参数调用 stream 函数。上下文没有退出,因此套接字不会过早关闭。

此外,我还使用了 thread 对象的 start() 方法来启动线程。

© www.soinside.com 2019 - 2024. All rights reserved.