我正在使用此代码(非常简化的原始版本,但问题仍然存在)来复制文件:
def copyfileobj_example(source, dest, buffer_size=1024*1024):
while 1:
copy_buffer = source.read(buffer_size)
if not copy_buffer:
break
dest.write(copy_buffer)
如果我在没有pyqt的情况下调用该函数,文件将被快速复制,但是当我在一个简单的pyqt窗口中调用它时,副本的速度会慢三倍。
快速复制大量文件是应用程序的主要观点,我认为包括gui会慢一点,但没有让它慢三倍!并使用线程或多进程运行复制功能不会带来令人满意的改进。
这就是这样吗?你能推荐一些解决这个性能问题的东西吗?
编辑:There是我的实际复制代码的要点,使用和不使用PyQT运行
答案 0 :(得分:5)
这可能是GIL的影响。随着PyQt在UI线程中运行,它每次必须处理事件时“窃取”GIL。这意味着您的循环每次都会停止。当你在另一个线程中运行时也会发生这种情况;锁是全球。
解决方法:
答案 1 :(得分:2)
由于我无法使问题中的链接代码生效(它只是挂起并使用100%CPU),我将发布一个更健全的示例用于测试。
使用下面的测试用例,我在复制400MB文件(三次运行)时得到以下输出:
$ python copy_test.py
2.9546546936035156
2.9658050537109375
$ python copy_test.py
3.226983070373535
3.192814826965332
$ python copy_test.py
2.935734748840332
2.8552770614624023
如您所见,没有显着差异。为清楚起见,这是在Linux上使用以下设置:
Python 3.5.0, Qt 5.5.0, PyQt 5.5
我得到了与Python 2.7 / 3.5,PyQt 4/5的所有组合类似的结果。
以下是测试用例:
import sys
import time
import os
SRC_FILE = '/home/tmp/source/test/test.zip'
DEST_FILE = '/home/tmp/source/test/test-copy.zip'
def copy_file(src, dst=[], progress=None, only_new_file=True):
size = 1024 * 1024
with open(src, 'rb') as s, open(dst[0], 'wb') as d:
while 1:
copy_buffer = s.read(size)
if not copy_buffer:
break
d.write(copy_buffer)
if __name__ == '__main__':
initTime = time.time()
copy_file(SRC_FILE, [DST_FILE], only_new_file=False)
print (time.time() - initTime)
time.sleep(5)
from PyQt5.QtWidgets import QApplication, QWidget
# from PyQt4.QtGui import QApplication, QWidget
app = QApplication(sys.argv)
w = QWidget()
w.resize(250, 150)
w.move(300, 300)
w.setWindowTitle('Simple')
w.show()
initTime = time.time()
copy_file(SRC_FILE, [DST_FILE], only_new_file=False)
print (time.time() - initTime)
sys.exit(app.exec_())