Python:插座.rcvfrom()锁定所有纸条

2024-05-28 18:08:39 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Python3中使用schedule和socket编写了一个简单的代码:

import schedule
import socket
from time import sleep

def readDataFromFile():
    data = []
    with open("/tmp/tmp.txt", "r") as f:
        for singleLine in f.readlines():
            data.append(str(singleLine))

    if(len(data)>0):
        writeToBuffer(data)

def readDataFromUDP():
    udpData = []
    rcvData, addr = sock.recvfrom(256)
    udpData.append(rcvData.decode('ascii'))

    if(len(udpData)>0):
        writeToBuffer(udpData)

.
.
.

def main():
    schedule.every().second.do(readDataFromFile)
    schedule.every().second.do(readDataFromUDP)

    while(1):
        schedule.run_pending()
        sleep(1)



UDP_IP = "192.xxx.xxx.xxx"
UDP_PORT = xxxx

sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.bind((UDP_IP, UDP_PORT))

main()

问题是,脚本挂在插座.rcvfrom()指令,并等待数据到来。 如何强制python独立运行此作业?更好的办法是在线程中运行它?你知道吗


Tags: importdataifdefsleepsockettmpxxx
1条回答
网友
1楼 · 发布于 2024-05-28 18:08:39

您可以在这里使用线程,它可以正常工作,但需要做一些更改。首先,后台线程上的调度程序将尝试每秒启动一个新的recvfrom,不管最后一个花了多长时间。其次,由于两个线程显然都在试图调用相同的writeToBuffer函数,因此您可能需要一个Lock或其他东西来同步它们。你知道吗

在这里,围绕异步事件循环重写整个程序几乎肯定是过火了。你知道吗

将套接字更改为非阻塞并进行混合可能是最简单的更改,例如,使用^{}

# wherever you create your socket
sock.settimeout(0.8)

# ...

def readDataFromUDP():
    udpData = []
    try:
        rcvData, addr = sock.recvfrom(256)
    except socket.timeout:
        return
    udpData.append(rcvData.decode('ascii'))

    if(len(udpData)>0):
        writeToBuffer(udpData)

现在,每次调用recvfrom,如果有可用的数据,您将立即处理它;如果没有,它将等待0.8秒,然后引发异常,这意味着您没有要处理的数据,因此返回并等待下一个循环。(0.8并没有什么神奇的地方;我只是觉得不到1秒的时间是个好主意,所以在下一个时间表时间到来之前,还有时间做所有其他的工作。)

实际上,这是通过将操作系统级套接字设置为非阻塞模式,并执行一些特定于实现的操作来等待超时。通过使用setblocking(False)并使用selectselectors模块等待0.8秒套接字准备就绪,您自己也可以做到这一点,但是让Python为您处理这一点更容易。你知道吗

相关问题 更多 >

    热门问题