对于一个我要通过安全网络通过tcp转储数据的项目,我试图编写一个开发测试服务器以简化测试过程。我有服务器,它基本上只接收数据并将其打印到终端。
但是,我对当前的Sigint处理实现感到不满意。
我尝试使用信号处理程序,并且尝试/ except / finally阻止各种配置,但无济于事。
这是测试服务器的代码
#!/usr/bin/env python3
import socket
import sys
host = ''
port = 5000
try:
with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
s.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
s.bind((host, port))
s.listen(1)
conn, addr = s.accept()
with conn:
print("Connected by", str(addr))
while True:
data = conn.recv(1024).decode()
if not data:
break
print(str(data))
except KeyboardInterrupt:
print("Quitting...")
finally:
sys.exit()
此版本退出时没有堆栈跟踪...那么,别无其他。
这是我尝试过的事情和问题:
(在收听时)使用全局“监听”变量(而不是while)为True,在这种情况下,sigint处理程序会将变量设置为false。这意味着,如果tcp套接字从未接受任何数据,它将根本不会以sigint终止,并且有必要使用sigquit或sigkill
在while True块中或之前使用try catch块。再一次,在接受连接之前,这实际上并没有任何帮助。
使用try catch捕获整个带块的主数据库。这意味着我只能退出并伪造正常关机,而实际上却不能。另外,我认为这与使用with块开头的原则背道而驰。 (而且我不确定这种方法是否会关闭套接字,或者是否有必要)
答案 0 :(得分:1)
这里有很多选择,具体取决于您的关注点。就像现在写的那样...不,如果您的print
只是一长串操作,那么如果您按Ctrl-C,它不一定完成。
您可以做的一件事是用SIGINT
暂时阻止signal.pthread_sigmask
信号,例如,如果您不想中断关键操作,然后再屏蔽它(此时,SIGINT
将照常流向KeyboardInterrupt
)。也可以通过上下文管理器来实现,如下所示:
#!/usr/bin/env python3
import signal
class SignalMasker:
""" Temporarily block signals. """
def __init__(self, sigs):
self.sigs = set(sigs)
def __enter__(self):
signal.pthread_sigmask(signal.SIG_BLOCK, self.sigs)
return self
def __exit__(self, *args):
signal.pthread_sigmask(signal.SIG_UNBLOCK, self.sigs)
return None
if __name__ == '__main__':
import time
interrupted = True
try:
with SignalMasker([signal.SIGINT]):
# Should not be able to interrupt this before 5 seconds expired
time.sleep(5)
interrupted = False
except KeyboardInterrupt:
print("\nGot keyboard interrupt")
assert not interrupted
如果您唯一要确保的是关闭文件描述符并避免堆栈跟踪,那么现在您可以使用了。