前言
努力是为了让你的目标更明确,但方向若错了,那可能就成了最遗憾的意外了
今天学习一下Python里的多线程的应用。但大家要清楚什么是线程,什么是进程,要区分二者概念
1 概念
什么是线程?
线程是一个轻量级的子进程,是最小的处理单元。可以说线程是进程的子集。
线程是独立的,一个线程发生错误,不影响其他线程正常执行。
什么是进程?
进程是指正在运行中的应用程序。每个进程都有自己独立的内存空间,当用户启动一个进程时,操作系统就会为该进程分配一个独立的内存空间,让应用程序在独立内存中运行
2 多线程
我们知道python是解释型语言,程序是从上向下解释一句执行一句,如果上面的程序出现的死循环,则下方的程序时不会执行的。接下来就做一个简单的测试。
import time # 导入时间模块
def test1():
while True:
print("线程1")
time.sleep(1) # 延时1秒防止数据太快
def test2():
while True:
print("线程2")
time.sleep(1) # 延时1秒防止数据太快
if __name__ == '__main__':
test1()
test2()
我们可以看到程序执行到test(1)时进入了死循环,所以test(2)不执行。那么如何处理这类问题呢?这里我们就要用到多进程处理。
多进程处理
这里用到了一个模块threading
首先导入这个模块
import threading # 导入线程模块
import time # 导入时间模块
# 定义一个线程1函数
def test1():
while True:
print("线程1")
time.sleep(1) # 延时1秒防止数据太快
# 定义一个线程2函数
def test2():
while True:
print("线程2")
time.sleep(1) # 延时1秒防止数据太快
if __name__ == '__main__':
t1 = threading.Thread(target=test1) # 设置为线程
t1.start() # 开启线程1
t2 = threading.Thread(target=test2) # 设置为线程
t2.start() # 开启线程2
执行效果
从上面的图片我们可以看出当线程处理时,并不是线程1执行一句,线程2执行一句,而是二者随机执行,所以在相同时间内,线程1和线程2执行的次数不一样多。这个就需要我们特别注意,用多线程处理全局变量时可能会出错。
我们说过一个线程出错不会影响其他线程
现在来做一个简单测试。
执行效果
我们可以看到当线程1出错时,并不影响线程2的执行,所以线程互相不影响。
PyQt5中的线程操作
就拿最简单的例子来说,在一个窗口实时显示刷新当前的时间
接下来就是代码的处理
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5 import QtCore, QtGui, QtWidgets
import time
class backendthread(QThread): # 声明一个类
updata = pyqtSignal(str) # 一个字符串的类的信号
def run(self):
while True:
data = time.ctime() # 获取本地时间
self.updata.emit(str(data))
time.sleep(1) # 睡眠一秒
注意导入相关线程和信号类库。如果是用QTdesigner生成的py代码,就要在生成的代码里去写
写完信号后我们要写一个槽去用这个信号
def initUI(self):
self.back= backendthread()
self.back.updata.connect(self.display) # 链接到一个display槽函数
self.back.start()
def display(self,data): # 编写这个槽函数
self.text2.setText(data) # 将时间显示出来
下面定义的def initUI(self):函数,注意在前面的def setupUi(self, Form):下面添加
最后我附上我的这个用designer生成并修改后的登录界面的py文件的所有程序,由于里面的控件多所以程序也多,大家只用看第一个函数和后面两个函数就可以了。
我没有给出我的main.py,但上几篇博客里已经给出来。由于今天没修改main.py,所以没必要给,不然代码会更多。
from PyQt5.QtCore import QThread, pyqtSignal
from PyQt5 import QtCore, QtGui, QtWidgets
import time
class backendthread(QThread):
updata = pyqtSignal(str)
def run(self):
while True:
data = time.ctime()
self.updata.emit(str(data))
time.sleep(1)
class Ui_Form(object):
def setupUi(self, Form):
Form.setObjectName("Form")
Form.resize(861, 479)
Form.setBaseSize(QtCore.QSize(0, 0))
Form.setStyleSheet("\n"
"QWidget {\n"
"border-image:url(C:/Users/DELL/Pictures/Saved Pictures/1.jpg);\n"
"}\n"
"\n"
"QTextBrowser {\n"
"border-image:url();\n"
"}\n"
"QLineEdit {\n"
"border-image:url();\n"
"}\n"
"QComboBox {\n"
"border-image:url();\n"
"}\n"
"QLabel {\n"
"border-image:url();\n"
"}\n"
"QPushButton {\n"
"border-image:url();\n"
"}")
self.horizontalLayout = QtWidgets.QHBoxLayout(Form)
self.horizontalLayout.setObjectName("horizontalLayout")
self.verticalLayout = QtWidgets.QVBoxLayout()
self.verticalLayout.setObjectName("verticalLayout")
spacerItem = QtWidgets.QSpacerItem(20, 40, QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Expanding)
self.verticalLayout.addItem(spacerItem)
self.textBrowser = QtWidgets