最近在做深度学习发现下载模型时速度太慢,可能是外网的原因。所以做了一个小插件,利用远程服务器辅助下载文件。
你需要准备:
远程服务器(具备TCP接口)、本地电脑(python环境)
所需知识:
1、PYQT基础知识
2、TCP知识
3、QT多线程知识
PYQT做界面 & 多线程
如果你对PYQT不太了解,参考可以五分钟掌握。
如图所示,我们搭建了我们的UI界面,主要三个部分:端口号,下载链接,日志。
代码可以参考:
class Example(QWidget):
def __init__(self):
super().__init__()
self.ok = False
self.port_default = 0
self.content_tmp = ''
self.initUI()
#UI界面涉及
def initUI(self):
#1 说明内容
self.lbl2 = QLabel(self)
self.lbl2.setText(
"1、You should input Port first.\n2、Enter the URL and click the download button\n3、If you have some problem, send email to\n menglingjun@cloudcver.com")
self.lbl2.move(30, 10)
#2 下载区
#2.1 文本URL
self.lbl = QLabel(self)
self.lbl.setText("Url:")
self.lbl.move(30, 93)
#2.2 链接URL
self.file_url = QLineEdit(self)
self.file_url.move(50, 90)
self.file_url.setGeometry(50, 90, 250, 23)
#2.3 下载按钮
download_button = QPushButton('Download', self)
download_button.clicked.connect(self.download)
download_button.move(320, 90)
#3 端口号按钮
self.download_button = QPushButton('No Port', self)
self.download_button.clicked.connect(self.login)
self.download_button.move(400, 10)
#4 日志
self.tmp = QTextEdit(self)
self.tmp.move(50, 120)
self.tmp.setGeometry(50, 120, 350, 70)
#5 标题
self.setGeometry(300, 300, 500, 200)
self.setWindowTitle('服务器加速下载器@cloudcver')
self.show()
def login(self):
text, ok = QInputDialog.getText(self, 'Set Port',
'Enter your port:')
if ok:
self.port_default = int(text)
self.download_button.setText(text)
self.content_tmp = self.content_tmp + "%s:Set port at %s\n"%(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),text)
self.tmp.setText(self.content_tmp)
self.ok = True
def download(self):
if self.ok:
self.content_tmp = self.content_tmp + "%s:Send the task to server\n" % (
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
self.tmp.setText(self.content_tmp)
self.thread = DownloadThread()
self.thread.set_port_url(self.port_default,self.file_url.text()) # 创建
self.thread.trigger.connect(self.finish) # 连接信号
self.thread.start() # 开始线程
else:
reply = QMessageBox.question(self, 'Message',
"You should set port first", QMessageBox.Yes)
def finish(self):
self.content_tmp = self.content_tmp + "%s:Finish!\n" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
self.tmp.setText(self.content_tmp)
界面很简单就不说了,主要说一下多线程内容!
重点看一下这里!
重点看一下这里!
重点看一下这里!
1、看download函数,ok这个参数代表已经设定好端口号。初始ok是False,在Port按钮输入后就变为True了。
2、这里我们启动了一个多线程DownloadThread(),其定义了一个线程类,这个类下面有几个方法:
2.1 set_port_url()是我们自己定义的方法,为了设定一些参数。
2.2 run是一个父类的函数,我们需要重构一下,这就是当执行线程时需要执行的函数。也就是self.thread.start() 后就开始执行run这个函数。
2.3 trigger是我们创建的一个pyqt信号,我们可以让它连接一个函数,然后在run执行完后传递退出的信号,代表推出后执行它连接的函数。
具体的代码可以看:
class DownloadThread(QThread):
trigger = pyqtSignal()
def __int__(self):
super(DownloadThread, self).__init__()
def set_port_url(self,port_default,url):
self.port_default = port_default
self.url = url
def run(self):
##一会补充!
# # 循环完毕后发出信号
# print('1线程运行完了')
self.trigger.emit()
TCP服务
全部代码
服务器端:
#encoding=utf-8
#
import subprocess
import os
import sys
import time
reload(sys)
sys.setdefaultencoding('utf8')
#testurl = "http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz"
#subprocess.call('wget -P ./tmp/ %s'%testurl,shell = True)
from socket import *
import socket
def send_file_to_client(new_client_socket, client_addr):
# 1.接收客户端发过来需要下载的文件名
file_name = new_client_socket.recv(1024).decode("utf-8")
print("客户端(%s)需要下载的文件是:%s"%(str(client_addr),file_name))
file_time = time.time()
subprocess.call('wget -P ./tmp/%s/ %s'%(file_time,file_name),shell = True)
file_content = None
# 2.打开这个文件,读取数据
try:
index = os.listdir('./tmp/%s/'%file_time)
new_client_socket.send(index[0])
filesize = str(os.path.getsize(os.path.join('./tmp/%s/'%file_time,index[0])))
print(os.path.join('./tmp/%s/'%file_time,index[0]))
print(filesize)
#new_client_socket.send('12345')
new_client_socket.send(filesize)
print('wait')
data = new_client_socket.recv(1024)
f = open(os.path.join('./tmp/%s/'%file_time,index[0]), "rb")
print('open!')
new_client_socket.sendall(f.read())
print('send!ok')
'''
while True:
for line in f:
new_client_socket.send(line)
#print('sending...')
#new_client_socket.send('end')
break
print('ok')
'''
f.close()
except Exception as ret:
print("没有要下载的文件(%s)" % file_name)
def main():
# 1.创建套接字 socket
tcp_sever_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 2.绑定本地信息 bind
tcp_sever_socket.bind(("",70))# 7890))
# 3.让默认的套接字由主动变为被动 listen
tcp_sever_socket.listen(128)
# 4.等待客户端的链接 accept
while True:
print('wait')
new_client_socket, client_addr = tcp_sever_socket.accept()
print('connect!')
# 5.调用发送文件函数,完成客户端服务
send_file_to_client(new_client_socket, client_addr)
print('send!')
# 6.关闭套接字
new_client_socket.close()
tcp_sever_socket.close()
if __name__ == '__main__':
main()
客户端:
# download from fuwuqi
# Author: menglingjun@cloudcver.com
#
#package
import socket
import time
from PyQt5.QtWidgets import QWidget, QPushButton, QApplication,QLabel,QLineEdit,QMessageBox,QInputDialog,QTextEdit
from PyQt5.QtCore import QCoreApplication
from PyQt5.QtCore import Qt, QThread,pyqtSignal
import sys
class DownloadThread(QThread):
trigger = pyqtSignal(int,str)
def __int__(self):
super(DownloadThread, self).__init__()
def set_port_url(self,port_default,url):
self.port_default = port_default
self.url = url
def run(self):
try:
# 1.创建套接字
tcp_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
IP_default = '39.97.178.93'
# 2.获取服务器的ip port
# dest_ip = input("请输入下载服务器的ip:")
# dest_port = int(input("请输入下载服务器的port:"))
print(3)
# 3.链接服务器
tcp_socket.connect((IP_default, self.port_default))
# 4.获取文件下载的文件名
# download_file_name = input("请输入要下载的文件名字:")
download_file_name = self.url
# 'http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz'
# 5.将文件名字发送到服务器
tcp_socket.send(download_file_name.encode("utf-8"))
print(4)
# 6.接收文件中的数据
filename = tcp_socket.recv(1024)
print(filename)
data1 = tcp_socket.recv(1024)
tcp_socket.send(data1)
#data2 = tcp_socket.recv(1024)
print(data1)
#print(data2)
file_total_size = int(data1.decode())
print(file_total_size)
received_size = 0
f = open(filename, 'wb')
while received_size < file_total_size:
data = tcp_socket.recv(2048000)
f.write(data)
received_size += len(data)
print('已接收 ', received_size, ' Byte')
#data = tcp_socket.recv(file_total_size)
#f.write(data)
print("---")
#data = tcp_socket.recv(1024)
#print("file save to %s" % filename)
# 8.关闭套接字
tcp_socket.close()
# 这一部分就可以写入你想要执行的代码就好
# print('开始执行了run')
# for i in range(2000000000):
# pass
#
# # 循环完毕后发出信号
# print('1线程运行完了')
#self.trigger.emit()
self.trigger.emit(1,str(filename))
except:
print("下载失败了")
self.trigger.emit(0,'-')
#http://download.tensorflow.org/models/resnet_v1_101_2016_08_28.tar.gz
## 窗口
class Example(QWidget):
def __init__(self):
super().__init__()
self.ok = False
self.port_default = 0
self.content_tmp = ''
self.initUI()
#UI界面涉及
def initUI(self):
#1 说明内容
self.lbl2 = QLabel(self)
self.lbl2.setText(
"1、You should input Port first.\n2、Enter the URL and click the download button\n3、If you have some problem, send email to\n menglingjun@cloudcver.com")
self.lbl2.move(30, 10)
#2 下载区
#2.1 文本URL
self.lbl = QLabel(self)
self.lbl.setText("Url:")
self.lbl.move(30, 93)
#2.2 链接URL
self.file_url = QLineEdit(self)
self.file_url.move(50, 90)
self.file_url.setGeometry(50, 90, 250, 23)
#2.3 下载按钮
download_button = QPushButton('Download', self)
download_button.clicked.connect(self.download)
download_button.move(320, 90)
#3 端口号按钮
self.download_button = QPushButton('No Port', self)
self.download_button.clicked.connect(self.login)
self.download_button.move(400, 10)
#4 日志
self.tmp = QTextEdit(self)
self.tmp.move(50, 120)
self.tmp.setGeometry(50, 120, 350, 70)
#5 标题
self.setGeometry(300, 300, 500, 200)
self.setWindowTitle('服务器加速下载器@cloudcver')
self.show()
def login(self):
text, ok = QInputDialog.getText(self, 'Set Port',
'Enter your port:')
if ok:
self.port_default = int(text)
self.download_button.setText(text)
self.content_tmp = self.content_tmp + "%s:Set port at %s\n"%(time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()),text)
self.tmp.setText(self.content_tmp)
self.ok = True
def download(self):
if self.ok:
self.content_tmp = self.content_tmp + "%s:Send the task to server\n" % (
time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
self.tmp.setText(self.content_tmp)
self.thread = DownloadThread()
self.thread.set_port_url(self.port_default,self.file_url.text()) # 创建
self.thread.trigger.connect(self.finish) # 连接信号
self.thread.start() # 开始线程
else:
reply = QMessageBox.question(self, 'Message',
"You should set port first", QMessageBox.Yes)
def finish(self,status,filename):
print("sdsd")
if status == 1:
self.content_tmp = self.content_tmp + "%s:Finish! file save to %s\n" % ((time.strftime("%Y-%m-%d %H:%M:%S", time.localtime())),filename)
else:
self.content_tmp = self.content_tmp + "%s:Fail!\n" % (time.strftime("%Y-%m-%d %H:%M:%S", time.localtime()))
self.tmp.setText(self.content_tmp)
if __name__ == '__main__':
app = QApplication(sys.argv)
ex = Example()
sys.exit(app.exec_())