首页 > 编程学习 > Qt+Python多次刷新缓存的问题及项目延伸:

场景:

在一个槽函数中,new一个QProcess类对象或是最多20个QProcess类对象,每个QProcess类对象中开启一个exe进程或是直接使用python.exe打开.py文件,设置通信管道为standardoutput,绑定==readyReadStandardOutput()信号或readyread()信号到自定义槽函数中,因为需要多次print和有多个子进程,connect的连接方式使用QueuedConnection,然后start()waitForStarted(),在该自定义槽函数中,使用readline()==读取一行数据,以/n作为分隔符。最后在.exe或.py进程中,使用print(…, flush=True)或sys.stdout.write()sys.stdout.flush()向主进程中写入数据。

问题及原因:

现象:QProcess对象开启的python进程向主进程写入数据时,连续的print()或sys.stdout.write()可能会只触发一次readyReadStandardoutput信号。多出来的print数据会保留在缓冲区。在下一次print的时候,一并打印。需求:项目的需求是连续的print()需要正确的按照print()的次数去触发相应次数的信号。

问题解决:

首先要理解readyReadStandardoutput()及readyread()信号的含义,可以查看官方文档。
1、首先,当第一句print数据从子进程(.py.exe通过print发送数据到系统)到主进程缓冲区时,readyread信号触发一次,如果此时readyread槽函数还没有及时执行,又有新的数据到来(比如我们这里的多次print),而且来了很多次,那么所有的都将会只触发一次readyread信号,但是数据还是已经从子进程成功写到了主进程缓冲区。正在等待处理,但是已经不会主动去处理了。如果此时你的readyread槽函数执行了,那么这时候来的新的数据就会触发第三个readyread信号,就会把之前未触发的print一起触发了。也就是说,还没有响应的readyread信号最多只有两个
2、简单的理解就是官方文档中的only once。当数据刚到达缓冲时,主进程会触发一次readyread信号,而如果这时候还没有执行readyread信号,信号还在消息队列中,这时又来了多次数据,那么就不会触发信号。通俗的理解就是:因为python程序的连续的print执行过快,向系统缓冲区写入数据时,主程序只反应了一次信号。关键就是速度过快来不及!!

官方资料:

官方对readyread信号的说明:This signal is emitted once every time new data is available for reading from the device’s current read channel. It will only be emitted again once new data is available, such as when a new payload of network data has arrived on your network socket, or when a new block of data has been appended to your device.
翻译:
每一次,在当前用来存放读数据的位置中(也就是可读缓冲区),有可读数据可用,都会发送这个信号。当新的数据到来的时候,这个信号还会再发送且仅发送一次。比如:新的网络数据到达你的网络socket,或者新的数据块添加到你的设备。

每当新数据可用于从设备的当前读取通道读取时,该信号就会发出一次。只有当新数据可用时,例如当网络数据的新有效载荷到达网络套接字时,或者当新数据块附加到设备时,才会再次发出该消息。

只要是readyread类的信号,不干事QTCPSocket还是QProcess都是一样的逻辑。

补充:

  1. 设置通信管道为标准输出,并不影响QProcess对象->write()向.py文件中写入信息
  2. 创建QThrea对象时,这个对象所属的线程还是主线程,只不过run()函数所在的线程是子线程。同理QProcess也是一样,QProcess对象属于创建对象所在的线程及主线程,只是负责管理开创的进程。
Copyright © 2010-2022 dgrt.cn 版权所有 |关于我们| 联系方式