从无限的while循环中在函数之间传递数据
Posted
技术标签:
【中文标题】从无限的while循环中在函数之间传递数据【英文标题】:Passing data between functions from endless while loop 【发布时间】:2022-01-05 18:14:33 【问题描述】:一直在努力让它工作,因为我无法在不会结束的 while 循环中使用 return
。
简而言之,我在一个函数receive()
(无限循环)的套接字客户端中接收到一条消息,并且需要将该传入消息的结果传递给main()
。尝试使用yield
,因为我不确定还有什么可以实现这一点。我创建了另一个函数来尝试在receive()
函数中捕获yield
。
我知道初始消息到达服务器是因为它输出了消息,并且我知道客户端正在接收服务器的确认消息,因为它正在打印它。我只是没有运气将该数据传递给main()
,因此其余代码将无法正常工作。
我对此很陌生,所以我可能做错了。我应该使用类来更轻松地共享数据,但还没有充分掌握它们。希望使用 yield 或其他方法可以解决这个问题。
接收函数:
def receive():
while True:
try:
incoming = client.recv(2048).decode(FORMAT)
if 'RECEIVED' in incoming:
confirmation = 'confirmed'
yield confirmation
print(incoming)
except:
print("Connection interrupted.")
client.close()
break
#------------
# also tried
#------------
def receive():
while True:
try:
incoming = client.recv(2048).decode(FORMAT)
if 'RECEIVED:COMPLETE' in incoming:
confirmation = 'confirmed'
else:
confirmation = 'unconfirmed'
yield confirmation
except:
print("Connection interrupted.")
client.close()
break
返回函数:
def pass_return(passed_return_value):
passed_return_value
主函数(带有各种测试)
def main():
pass_return(receive())
# Bunch of code
if something == True:
send("some message")
time.sleep(.25)
try:
if confirmation == 'confirmed':
# do the business here
#------------
# also tried
#------------
def main():
# Bunch of code
if something == True:
send("some message")
time.sleep(.25)
pass_return(receive())
try:
if confirmation == 'confirmed':
# do the business here
#------------
# also tried
#------------
def main():
r = pass_return(receive())
# Bunch of code
if something == True:
send("some message")
time.sleep(.25)
try:
if r == 'confirmed':
# do the business here
#------------
# even tried
#------------
def main():
# Bunch of code
if something == True:
send("some message")
time.sleep(.25)
r = pass_return(receive())
try:
if r == 'confirmed':
# do the business here
我声明变量 confirmation
OUTSIDE of main()
和 receive()
(在我的常量所在的文件顶部),否则我会收到 confirmation is undefined
的错误。
如果我在main()
中print
confirmation
,它要么不打印,要么不打印None
,所以我猜它只是得到confirmation
的初始空值而不是yield
。
# constants above here
confirmation = str()
# code and such
def pass_return(passed_return_value):
passed_return_value
def receive():
#code...
def main():
#code...
if __name__ == '__main__':
main()
【问题讨论】:
编写以非阻塞方式正确处理此类事情的代码是一个非常广泛的主题。您可能想了解现有框架是如何做到这一点的(例如,Python 的 Discord API)。 【参考方案1】:请注意,Python 是单线程的。如果您的程序应该什么都不做,只是等待来自外部源的数据到达套接字并对其做出反应,那么这将起作用:
def receive():
while True:
try:
incoming = client.recv(2048).decode(FORMAT)
if 'RECEIVED' in incoming:
yield 'status': 'confirmed', 'message': incoming
else:
yield 'status': 'unconfirmed', 'message': incoming
except:
print("Connection interrupted.")
client.close()
break
def main():
for message in receive():
print(message)
在这里,该程序的大部分时间将花在client.recv(2048)
上。 This is a blocking call. 在收到请求的字节数之前它不会返回。在此期间,您的程序中不会发生任何其他事情。
一旦收到字节,就可以yield
,main()
内部的for
循环可以处理数据。完成后,程序流将返回到client.recv(2048)
并坐在那里。
如果您希望程序在也侦听该套接字上的数据时发生不同的事情,则需要研究多线程,并将此代码放在后台线程上。
【讨论】:
这个程序的工作方式是它最初连接到服务器,然后它做它需要做的事情,然后它联系服务器让它知道它完成了它的任务,sleep a tick,然后检查对于确认,打印确认,然后结束。我确实有另一个等待的脚本。我会在两者中尝试这个。感谢您的建议。 @liquidRock 如果您已经将事物拆分为服务器和客户端,请在单独的进程中运行它们。这与多线程一样好,而且麻烦更少。 是的,服务器在自己的环境中的一个脚本中。每个客户端都是他们自己的脚本,一些在相同的环境中,一些在不同的环境中。您的意思是使用多处理使receive
函数与客户端中的main
分开处理吗?我假设客户端将需要多处理或多线程,因为添加它在启动时无法再连接到服务器的代码(我假设它正在等待接收以获取该结果)。
我不关注。一方面,您似乎混淆了“客户端”和“服务器”的概念。侦听端口并等待请求的程序不是客户端,而是服务器。发送请求和接收响应的程序是客户端。不,我并不是说receive()
和main()
应该在不同的线程上,请再次阅读我的答案。我说“如果您的程序除了等待数据从外部源到达套接字并对其做出反应之外什么都不做,那么这将起作用”。
由于代码的一些创造性定位,我已经设法在一个脚本中实现了这个工作,而无需使用多线程,因此客户端脚本执行它需要的内容,然后在需要时等待产量到,并且仍然可以在需要时联系服务器。其他人将需要多线程,或者甚至 asyncio 可能会工作来等待产量。不管怎样,谢谢你的帮助。解决其余问题后,我会发布结果。以上是关于从无限的while循环中在函数之间传递数据的主要内容,如果未能解决你的问题,请参考以下文章
如何在 3 层(单层)应用程序中在 BLL 和 UI 之间传递数据?