Python QtNetwork-下载线程化文件
因此,我正在使用Python QtNetwork-下载线程化文件,python,download,pyqt4,qthread,qtnetwork,Python,Download,Pyqt4,Qthread,Qtnetwork,因此,我正在使用QNetworkAccessManager(当然还有NetworkReply和Request)进行一些下载。我可以让它在完全没有线程化的情况下完全正常工作,并阻塞应用程序,但是无论我尝试使用什么方法以非阻塞方式运行它,它都不会工作 似乎调用了NetworkAccessManager中的.get(),但要么从未连接,要么从未发送信号进行任何写入 如果您想知道为什么代码的某些部分是这样设置的,那么这是为了更容易地进行更改以尝试一系列不同的方法 我在书中读到的一件事是,尝试在一些信号发
QNetworkAccessManager
(当然还有NetworkReply
和Request
)进行一些下载。我可以让它在完全没有线程化的情况下完全正常工作,并阻塞应用程序,但是无论我尝试使用什么方法以非阻塞方式运行它,它都不会工作
似乎调用了NetworkAccessManager
中的.get()
,但要么从未连接,要么从未发送信号进行任何写入
如果您想知道为什么代码的某些部分是这样设置的,那么这是为了更容易地进行更改以尝试一系列不同的方法
我在书中读到的一件事是,尝试在一些信号发射上使用QtCore.QTimer.singleShot(0,CALL)
,将控制发送回主事件循环-尽管我尝试了,但没有任何效果
from PyQt4 import QtNetwork, QtCore, QtGui
import sys
import os
class Downloader(QtNetwork.QNetworkAccessManager):
def __init__(self, url, dest):
super(Downloader, self).__init__(None)
self.get_path = url
self.url = QtCore.QUrl(url)
self.download_buffer = QtCore.QByteArray()
self.dest = self.set_up_destination(dest)
# self.request = QtNetwork.QNetworkRequest(self.url)
# self.reply = self.get(self.request)
#
# self.reply.readyRead.connect(self.read_data)
self.finished.connect(self.write_finished)
print 'Downloader Inited'
def startDownload(self):
self.request = QtNetwork.QNetworkRequest(self.url)
self.reply = self.get(self.request)
self.reply.readyRead.connect(self.read_data)
def set_up_destination(self, dest):
if '.' in dest:
dir_dest = os.path.dirname(dest)
if not os.path.isdir(dir_dest):
os.makedirs(dir_dest)
return dest
else:
if not os.path.isdir(dest):
os.makedirs(dest)
base = os.path.basename(self.get_path)
return os.path.join(dest, base).replace('\\', '/')
def write_finished(self):
write_file = QtCore.QFile(self.dest)
if write_file.open(QtCore.QIODevice.WriteOnly):
write_file.write(self.download_buffer)
write_file.close()
print 'Wrote File: {0}'.format(os.path.basename(self.dest))
else:
print 'ERROR'
def read_data(self):
self.download_buffer += self.reply.readAll()
def print_progress(self, gotten, total):
gotten = gotten/float(1000000)
total = total/float(1000000)
self.total = total
divisor = total/5.0
if gotten > (divisor*self.notify_count):
self.notify_count += 1
print 'Downloaded {0}/{1} Mb'.format(gotten, total)
else:
pass
class DownloadForm(QtGui.QDialog):
def __init__(self, from_dir, to_dir):
super(DownloadForm, self).__init__(None)
self.from_dir = from_dir
self.to_dir = to_dir
self.downloaders = []
self.run_count = 0
self.done_count = 0
self.display_label = QtGui.QLabel('Downloading items...')
self.vlayout = QtGui.QVBoxLayout()
self.vlayout.addWidget(self.display_label)
self.setLayout(self.vlayout)
self.start_downloads(self.from_dir, self.to_dir)
def start_downloads(self, from_dir, to_dir):
items = os.path.listdir(from_dir)
items = [os.path.join(from_dir, x) for x in items]
self.run_count = len(items)
self.display_label.setText('Downloading {0} items...'.format(self.run_count))
for item in items:
print 'starting item: {0}'.format(os.path.basename(from_dir))
m = Downloader(item, to_dir)
m.finished.connect(self.adjust_run_count)
self.downloaders.append(m)
for item in self.downloaders:
item.startDownload()
@QtCore.pyqtSlot(object)
def adjust_run_count(self, v):
self.done_count += 1
if self.done_count >= self.run_count:
self.display_label.setText('All Items Finished!')
class Thread(QtCore.QThread):
def __init__(self, lst):
super(Thread, self).__init__(None)
self.lst = lst
def run(self):
for item in self.lst:
item.startDownload()
if __name__ == '__main__':
app = QtGui.QApplication([])
DIR1 = None #Give it a path to a folder containing some files
DIR2 = None #Give it a path to an empty folder to 'copy' to.
form = DownloadForm('DIR1',
'DIR2')
form.show()
app.exec_()
现在它被设置为在本地运行,只是为了让它工作
这是我最近的一次尝试(我想这是行不通的,但前几天我在某处看到了一篇类似的帖子,所以我想在来这里之前我会用尽一切资源——这篇文章真的很糟糕!!!)
我尝试过以下方法:
创建了一个线程(作为GUI的子线程),该线程实际生成了每个管理器对象,存储了一个变量,该变量取决于它生成了多少个管理器(例如,50个)将其完成信号连接到自己的插槽,该插槽将增加一个finished_count
var,直到达到50(意味着它们都完成了),然后该线程将发出自己的信号,或打印“完成”或其他内容
以类似的信号/插槽方式为每个作业制作单独的线程
大家都明白了,我还尝试了其他几种方法——它们都有共同点:
-涉及的QThreads
-要么A)不工作,要么B(更有可能)工作,我做错了
我在这里有点不知所措。
希望有人能帮忙