Python(9):一文学懂进程,线程和协程

文章目录

  • 一、进程
    • 1.创建多进程
    • 2.查看进程id
    • 3.进程池
    • 4.进程间的互相通信
  • 二、线程
    • 1.threading线程模块
    • 2.创建多线程
    • 3.互斥锁
    • 4.死锁
    • 5.线程间的互相通信
  • 三、协程
    • 1.认识协程
    • 2.gevent模块在爬虫中的应用
  • 四、多线程、多进程、协程的区别

分类定义
程序一个应用可以当做一个程序,比如qq软件。
进程程序运行的最小的资源分配单位,一个程序可以有多个进程。每个进程中至少有一个线程
线程cpu最小的调度单位,必须依赖进程而存在。
协程又称微线程、纤程。是一种比线程更加轻量级的并发方式,它不需要线程上下文切换的开销,可以在单线程中实现并发

一、进程

  • 多进程是指在同一台计算机中同时运行多个独立的进程。每个进程都有自己的地址空间,可用于执行一些特定的任务。这些进程可以同时执行,从而提高了程序的性能和效率。多进程可以在多核计算机上实现真正的并行计算,可以同时运行多个程序,从而大大提高了计算机的利用率。
  • 在多进程编程中,进程之间是独立的,它们各自运行自己的程序,有自己的地址空间和系统资源,不会相互干扰。每个进程都有自己的PID(进程标识符),它是一个唯一的标识符,用于在系统中识别该进程。多进程可以通过IPC(进程间通信)来实现数据共享和通信。
  • Python的多进程模块multiprocessing提供了一种方便的方法来创建和管理多个进程。它可以在单个Python解释器中创建多个进程,从而实现并行计算。此模块还提供了一些方便的功能,如进程池、进程通信和共享内存等。
  • 多进程编程可以在很多场景中提高程序的运行效率,如CPU密集型任务、I/O密集型任务、并行计算、大规模数据处理和机器学习等。但需要注意多进程之间的数据同步和通信,以避免数据竞争和死锁等问题。

1.创建多进程

①方式1:

import time
from multiprocessing import Process # 进程模块def sing():for i in range(1, 6):print('我在唱歌第{}句歌词'.format(i))time.sleep(1)def dance():for i in range(1, 6):print('我在跳舞第{}段舞蹈'.format(i))time.sleep(1)if __name__ == '__main__':t1 = Process(target=sing)  # ------------target=函数名t2 = Process(target=dance)t1.start()  # -------------------------启动该进程t2.start()

方式②:进程类创建

import os
import time
from multiprocessing import Processclass SubProcess(Process):def __init__(self, x):super().__init__()self.x = xdef run(self):  # 将父类的run函数重写,进程启动时候调用此方法for i in range(3):print('启动进程', i, os.getpid())time.sleep(1)if __name__ == '__main__':p = SubProcess(3)p.start()p1 = SubProcess(3)p1.start()'''启动进程 0 22064启动进程 0 10628启动进程 1 22064启动进程 1 10628启动进程 2 22064启动进程 2 10628'''

2.查看进程id

import os
from multiprocessing import Processdef fun1(n):print('参数为', n, '进程id为', os.getpid(), '父进程id为', os.getppid())  # 主进程id使用getppid方法def fun2(n):print('参数为', n, '进程id为', os.getpid(), '父进程id为', os.getppid())  # 子进程采用getpid方法if __name__ == '__main__':print('父进程:', os.getpid())t1 = Process(target=fun1, args=(32,))t2 = Process(target=fun2, args=(3232432,))  # 传入参数时候是按元组方式进行传入t1.start()t2.start()"""父进程: 22624参数为 32 进程id为 23272 父进程id为 22624参数为 3232432 进程id为 11100 父进程id为 22624"""

3.进程池

1.为什么使用进程池

由于进程启动的开销比较大,使用多进程的时候会导致大量内存空间被消耗。为了防止这种情况发生可以使用进程池,(由于启动线程的开销比较小,所以不需要线程池这种概念,多线程只会频繁得切换cpu导致系统变慢,并不会占用过多的内存空间)

2.进程池中常用方法

函数名作用
apply()同步执行(串行)
apply_async()异步执行(并行)
join()主进程等待所有子进程执行完毕。必须在close或terminate()之后。
close()等待所有进程结束后,才关闭进程池。

3.举例使用

from multiprocessing import Pool
import timedef downLoad(movie):for i in range(5):print(movie, '下载进度%.2f%%' % ((i + 1) / 5 * 100))time.sleep(1)return moviedef alert(name):print(name, '下载完成!')if __name__ == '__main__':movies = ['蔡徐坤吃饭视频', '蔡徐坤洗澡视频', '蔡徐坤化妆视频', '蔡徐坤擦口红视频']p = Pool(2)for movie in movies:p.apply_async(downLoad, args=(movie,), callback=alert)  # -----------callback函数回调,执行完第一个函数毁掉p.close()p.join()  # ----------------------------使主进程堵塞知道p进程执行完毕"""蔡徐坤吃饭视频 下载进度20.00%蔡徐坤洗澡视频 下载进度20.00%蔡徐坤吃饭视频 下载进度40.00%蔡徐坤洗澡视频 下载进度40.00%蔡徐坤洗澡视频 下载进度60.00%蔡徐坤吃饭视频 下载进度60.00%蔡徐坤洗澡视频 下载进度80.00%蔡徐坤吃饭视频 下载进度80.00%蔡徐坤吃饭视频 下载进度100.00%蔡徐坤洗澡视频 下载进度100.00%蔡徐坤化妆视频 下载进度20.00%蔡徐坤洗澡视频 下载完成!蔡徐坤擦口红视频 下载进度20.00%蔡徐坤吃饭视频 下载完成!蔡徐坤擦口红视频 下载进度40.00%蔡徐坤化妆视频 下载进度40.00%蔡徐坤擦口红视频 下载进度60.00%蔡徐坤化妆视频 下载进度60.00%蔡徐坤化妆视频 下载进度80.00%蔡徐坤擦口红视频 下载进度80.00%蔡徐坤化妆视频 下载进度100.00%蔡徐坤擦口红视频 下载进度100.00%蔡徐坤化妆视频 下载完成!蔡徐坤擦口红视频 下载完成!"""

4.进程间的互相通信

进程之间是各个独立的,要是进程与进程之间需要互相使用变量或者空间等等该怎么操作呢?方式有很多,这里我们使用Python的Queue队列(是一种先进先出的存储数据结构)

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-bucs01Wn-1625565694323)(C:\Users\qinfan\AppData\Roaming\Typora\typora-user-images\image-20210706175852363.png)]

举例:

from multiprocessing import Queuea=Queue() # 队列的最大容纳量
a.put(1)#传入数据
a.put(2)
a.put(3)while a.qsize()>0:#求出队列现在含有数据的长度,每取出一个数据长度会-1print(a.get(),end=' ')#取出数据# empty和full方法b=Queue(3)
print(b.empty())#队列空返回True
b.put(1)
b.put(1)
b.put(1)
print(b.full())#队列满返回True
结果:1 2 3 True True

二、线程

  • 线程是程序中一个更加轻量级的多路径执行实现方式。在系统级别,程序会根据系统为其提供的执行时间以及其他程序需要的执行时间统一调度执行。在程序内部,存在承载着不同任务的一个或多个同时或近乎同时执行的线程。实际上系统本身会管理线程的执行,调度其运行在某个核心上或在其他线程需要执行的时候强制中段该线程的执行。
  • 在非并发程序中,只有一个线程的执行。这个线程开始和结束于程序的main函数,并由一个接一个的不同方法或函数来实现程序的全部行为。相比之下,支持并发的程序可以启动一个线程,并按照需求增加线程以创建额外的执行路径。每一条新路径都有独立的自定义启动入口,在程序的main函数中独立运行代码。
  • 而多线程是指操作系统在单个进程内支持多个并发执行路径的能力,可以提高cpu的利用率。
  • python中使用threading模块来操作多线程。

1.threading线程模块

该模块的一些常见方法

函数名作用
threading.currentThread()返回当前的线程变量
threading.enumerate()返回一个包含正在运行的现成的list
threading.activeCount ()求正在运行的线程的列表长度

2.创建多线程

import threadingt=threading.Thread(target= 函数名,  # 需要执行的函数的名字args=(参数1,参数2...),  #  上述函数的参数,是个元组,无参数可不写,单个参数记住加,callback=回调函数 # 不需要回调可不写
)t.start()  # 线程启动

①创建方式1:

import threading
import timedef sing():for i in range(1, 6):print('我在唱歌第{}句歌词'.format(i))time.sleep(1)def dance():for i in range(1, 6):print('我在跳舞第{}段舞蹈'.format(i))time.sleep(1)if __name__ == '__main__':t1 = threading.Thread(target=sing)t2 = threading.Thread(target=dance)t1.start()t2.start()

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-GmPdsJ20-1625565694321)(C:\Users\qinfan\AppData\Roaming\Typora\typora-user-images\image-20210706171538461.png)]

②创建方式2:通过线程类

使用线程类的方法,需要继承父类的init方法,这里有几种继承方式

 调用父类的init方法有两种:#方法1:
super().init()#方法2:
super(MyThread, self).__init__() #方法3:
threading.Thread.__init__(self)

然后我们需要重写run方法,最后生成多个类对象,然后start调用

# -*- coding: utf-8 -*-
import time
from threading import Threadclass Test(Thread):def __init__(self):super().__init__()def sing(self):time.sleep(3)print('鸡你太美~~~~~')def run(self):self.sing()if __name__ == '__main__':# 五个线程for i in range(5):Test().start()

该程序运行后,理论上五次循环需要15s左右,但是使用该线程类,会实现并发运行,约等于3s左右运行

3.互斥锁

多个线程对公有变量处理时,容易造成数据的混乱,造成线程不安全

1.概念

互斥锁:当多个线程几乎同时修改某一个共享数据的时候,需要进行同步控制。线程同步能够保证多个线程安全访问“竞争资源”,最简单的同步机制就是引用互斥锁。互斥锁为资源引入一个状态:锁定/非锁定状态。某个线程要更改共享数据时,先将其锁定,此时资源状态为“锁定”,其它线程不能更改;直到当前线程释放资源,将资源变成"非锁定"状态,其它的线程才能再次锁定该资源。互斥锁保证了每次只有一个线程进行“写操作”,从而保证多个线程数据正确性。

2.锁的好处

  • 确定了某段代码只能由一个线程从头到尾完整地执行。
  • 保证全局变量的安全

3.锁的坏处

  • 阻止了多线程的并发执行,包含锁的某段代码实际上只能以单线程模块执行,效率大大地下降了。
  • 由于可以存在多个锁,不同的线程持有不同的锁,并试图获取对方持有的锁的时,可能会造成“死锁”。

3.使用步骤

from threading import Lock
l=LOCK()  #创建方式l.acquire()# 上锁方式
l.release()#-解锁方式

4.使用举例

举例:假设两个线程t1和t2都要对num进行+1操作,t1和t2都各自对num修改10次,num最终的值应该为20。紧接着我们把10次改为100000000次,由于多线程并发访问,有可能产生不一样的结果。
代码示例:

from threading import Threadg_num = 0
def test1():global g_numfor i in range(1000000):# g_num += 1b = g_num + 1g_num = bprint("---test1---g_num=%d"%g_num)def test2():global g_numfor i in range(1000000):a = g_num + 1g_num = aprint("---test2---g_num=%d"%g_num)
if __name__ == '__main__':p1 = Thread(target=test1)p1.start()p2 = Thread(target=test2)p2.start()#--------------------运行结果------------------------
---test2---g_num=1559989---test1---g_num=1516811

生成结果和我们预想的不一样,是因为没有控制多个线程对同一资源的访问,对数据造成破坏,使得线程运行的结果达不到预期。这种现象我们称为“线程不安全”,想要解决这种问题,我们使用互斥锁:

  • (1)p1被调用的时候,获取g_num=0,然后上一把锁,即不允许其它线程操作num。
  • (2)对num进行加1
  • (3)解锁,g_num = 1,其它的线程就可以使用g_num的值,而且g_num的值是而不是原来的0
  • (4)同理其它线程在对num进行修改时,都要先上锁,处理完成后再解锁。在上锁的整个过程中,不允许其它线程访问,保证了数据的正确性。

加入互斥锁后的代码:

import threading,timeg_num = 0#全局变量
def w1():global g_numfor i in range(10000000):       mutexFlag = mutex.acquire(True)#上锁if mutexFlag:g_num+=1 mutex.release()#解锁print("test1---g_num=%d"%g_num)def w2():global g_numfor i in range(10000000):mutexFlag = mutex.acquire(True)# 上锁if mutexFlag:g_num+=1mutex.release()# 解锁print("test2---g_num=%d" % g_num)if __name__ == "__main__":mutex = threading.Lock()#创建锁t1 = threading.Thread(target=w1)t1.start()t2 = threading.Thread(target=w2)t2.start()

4.死锁

1.死锁的产生

在线程间共享多个资源的时候,如果两个线程分别占有一部分资源并且同时等待对方的资源时,就会造成死锁。尽管死锁很少发生,但一旦发生就会造成应用的停止响应。常见有这两种情况:

  1. 同一个线程先后两次调用lock,在第二次调用时,由于锁已经被自己占用,该线程会挂起等待自己释放锁,由于该线程已被挂起而没有机会释放锁,因此 它将一直处于挂起等待状态,变为死锁;
  2. 线程A获得了锁1,线程B获得了锁2,这时线程A调用lock试图获得锁2,结果是需要挂起等待线程B释放锁2,而这时线程B也调用lock试图获得锁1,结果是需要挂起等待线程A释放锁1,于是线程A和B都在等待对方释放自己才释放,从而造成两个都永远处于挂起状态,造成死锁。

2.避免死锁发生

要最大可能地避免、预防和解除死锁。需要在系统设计、线程调度等方面注意如何确定资源的合理分配算法,避免线程永久占据系统资源。此外,也要防止线程在处于等待状态的情况下占用资源,在系统运行过程中,对线程发出的每一个系统能够满足的资源申请进行动态检查,并根据检查结果决定是否分配资源,若分配后系统可能发生死锁,则不予分配,否则予以分配。因此,对资源的分配要给予合理的规划。

5.线程间的互相通信

  • 关于线程与线程之间可以借助from queue import Queue来实现,此处不举例。
  • 进程与进程,线程与线程之间的通信借助队列来实现,一般常常配合redis来实现。

三、协程

1.认识协程

线程和协程都是实现并发编程的方式,但它们有一些不同的特点和应用场景。协程通常具有以下特点:

  • 协程中的代码可以暂停执行,并且在需要的时候可以恢复执行。
  • 多个协程可以在同一线程中并发执行,但是任意时刻只有一个协程在执行。
  • 协程通常是基于事件循环(Event Loop)实现的,事件循环负责调度协程的执行。

线程的并发编程通常会受到多线程竞争、死锁、上下文切换等问题的限制。在 Python 中,使用多线程编程需要注意线程安全、GIL等问题。而协程是一种轻量级的并发方式,它是在用户空间中实现的,并不依赖于操作系统的调度。协程可以在同一个线程中实现并发,不需要进行上下文切换,因此执行效率非常高。协程通常使用事件循环(Event Loop)来调度协程的执行,事件循环会在协程需要等待 IO 操作或者其他协程时,暂停当前协程的执行,执行其他协程,从而实现并发执行的效果。

协程在Python中历经了多次完善:

  • Python2.x 对协程的支持比较有限,通过 yield 关键字支持的生成器实现了一部分协程的功能但不完全
  • 第三方库 gevent 对协程有更好的支持。
  • Python3.4 中提供了 asyncio 模块。
  • Python3.5 中引入了 async/await 关键字。
  • Python3.6 中 asyncio 模块更加完善和稳定。
  • Python3.7 中内置了 async/await 关键字。

协程的应用场景:

  • 网络编程:协程可以帮助我们实现高并发的网络应用。
  • 异步IO:协程可以帮助我们高效地处理异步IO操作。
  • 数据库操作:协程可以帮助我们实现高并发的数据库应用。
  • 任务调度:协程可以帮助我们实现高效的任务调度系统。

2.gevent模块在爬虫中的应用

由于使用协程的方式有很多种,这里我使用gevent写一个爬虫demo

gevent模块简介

  • Python通过yield提供了对协程的基本支持,但是不完全。而第三方的gevent为Python提供了比较完善的协程支持。
  • gevent是第三方库,通过greenlet实现协程,其基本思想是: 当一个greenlet遇到IO操作时,比如访问网络,就自动切换到其他的greenlet,等到IO操作完成,再在适当的时候切换回来继续执行。由于IO操作非常耗时,经常使程序处于等待状态,有了gevent为我们自动切换协程,就保证总有greenlet在运行,而不是等待IO。
  • 使用gevent,可以获得极高的并发性能,但gevent通常只能在Unix/Linux下运行,在Windows下不保证正常安装和运行。

安装和依赖
依赖于greenlet 、library,支持python 2.6+ 、python 3.3+

pip install gevent

gevent协程爬虫示例

# coding: utf-8 
# 在导入其他库和模块前,先把monkey模块导入进来,并运行monkey.patch_all()。这样,才能先给程序打上补丁。
from gevent import monkey  # 从gevent库里导入了monkey模块,这个模块能将程序转换成可异步的程序monkey.patch_all()  # 它的作用其实就像你的电脑有时会弹出“是否要用补丁修补漏洞或更新”一样。它能给程序打上补丁,让程序变成是异步模式,而不是同步模式。它也叫“猴子补丁”。
import gevent
import requests
import timedef get_response(url):  # 定义一个函数,用来执行解析网址和爬取内容headers = {'User-Agent': 'Mozilla/5.0 (Windows NT 6.1; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/75.0.3770.142 Safari/537.36'}res = requests.get(url, headers=headers)  # 发出请求print(res.status_code)if __name__ == '__main__':start = time.time()  # 开始时间# 构建100个请求任务url_list = []for i in range(100):url = 'https://www.baidu.com/'url_list.append(url)# 使用协程tasks_list = []for url in url_list:# 用gevent.spawn()创建任务,此任务可以调用cra(url)函数,参数1函数名,后边为该函数需要的参数,按顺序写task = gevent.spawn(get_response, url)tasks_list.append(task)  # 将任务加入列表# 调用gevent库里的joinall方法,能启动执行tasks_list所有的任务。gevent.joinall(tasks_list)end = time.time()  # 结束时间print(end - start)

另外我们可以配合多进程+协程使用,可以更快提速。

四、多线程、多进程、协程的区别

优点缺点
多进程1.每个进程互相独立,不影响主程序的稳定性,子进程崩溃没关系;
2. 通过增加CPU,就可以容易扩充性能;
3.每个子进程都有2GB地址空间和相关资源,总体能够达到的性能上限非常大 。
1.逻辑控制复杂,需要和主程序交互;
2.需要跨进程边界,如果有大数据量传送,就不太好,适合小数据量传送、密集运算 多进程调度开销比较大。
多线程1.所有线程可以共享内存和变量
2.线程的执行开销比进程小。
1.每个线程与主程序共用地址空间,受限于2GB地址空间;
2. 线程之间的同步和加锁控制比较麻烦;
3.一个线程的崩溃可能影响到整个程序的稳定性;
协程(相比于线程)1.更加轻量级,占用的资源更少;
2.不需要进行上下文切换,执行效率更高;
3.可以使用事件循环进行调度,实现高并发的效果;
4.不会受到 GIL 的限制。
1.无法利用多核 CPU
2.调试困难等问题。。

在实际开发中,选择的并发方式从具体实际开发来进行选择。最好是采用结合的方式,来进行并发提速。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/809626.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

局域网共享文件夹怎么加密?局域网共享文件夹加密方法介绍

在企业局域网中,共享文件夹扮演着重要的角色。为了保护数据安全,我们需要加密保护局域网共享文件夹。那么,局域网共享文件夹怎么加密?下面我们来了解一下吧。 局域网共享文件夹加密方法 局域网共享文件夹加密推荐使用共享文件夹加…

【计算机考研】择校!北邮VS北航,哪所毕业以后就业好?

北邮计算机专业的就业优势相较于北航可能源于多方面的因素。 北邮在计算机和通信领域的实力备受肯定,被誉为"信息黄埔",这一声誉在一定程度上增强了北邮计算机专业毕业生的竞争力。 北邮的整体学校氛围和教育体系更加注重信息技术的发展和应…

vue表格操作列,按钮太多显示... 点击后悬浮显示全部按钮

效果: 分析原理: 一共就三步,仔细看看很简单,位置要加对,代码结构下边有demo 代码结构demo: <el-table-columnlabel"操作"align"center"fixed"right"show-overflow-tooltip><template slot-scope"scope"><el-buttonsi…

STM32电机控制固件架构

目录 一、应用程序剖析 二、面向现场的控制实现体系结构 1、参考计算循环 2、电流调节环路 3、安全回路 一、应用程序剖析 上图显示了由ST MC SDK构建的电机控制应用程序。首先&#xff0c;这样的应用程序是由电机控制工作台生成的软件项目&#xff0c;这要归功于STM32Cube…

01 SQL基础 -- 初识数据库与安装

一、初识数据库 数据库是将大量数据保存起来,通过计算机加工而成的可以进行高效访问的数据集合。该数据集合称为数据库(Database, DB)。用来管理数据库的计算机系统称为数据库管理系统(Database Management System, DBMS) 1.1 DBMS 的种类 DBMS 主要通过数据的保存格式…

【MySQL】数据库开篇

SueWakeup 个人主页&#xff1a;SueWakeup 系列专栏&#xff1a;学习技术栈 个性签名&#xff1a;保留赤子之心也许是种幸运吧 本文封面由 凯楠&#x1f4f8;友情提供 目录 本系列传送门 1. 什么是数据库&#xff1f; 2. 为什么使用数据库 3. 数据库的分类 4. NoSQL 与关系…

android android.permission.MANAGE_EXTERNAL_STORAGE使用

android11 及以上版本&#xff0c;如果release版本要读取外部存储公共目录&#xff0c;即sdcard公共目录&#xff0c;需要在androidManifest.xml下申明 <uses-permission android:name"android.permission.MANAGE_EXTERNAL_STORAGE" /> 如果要发版到海外&…

【UE Niagara】光束发射模块学习

效果 步骤 1. 新建一个Niagara发射器&#xff0c;使用Empty模板&#xff0c;这里命名为“NE_Beam” 打开“NE_Beam”&#xff0c;添加条带渲染器 添加“Spawn Burst Instantaneous”模块&#xff0c;设置生成数量为100 添加一个“Beam Emitter Setup”模块 再添加一个“Spawn …

Linux C应用编程:MQTT物联网

1 MQTT通信协议 MQTT&#xff08;Message Queuing Telemetry Transport&#xff0c;消息队列遥测传 输&#xff09;是一种基于客户端-服务端架构的消息传输协议&#xff0c;如今&#xff0c;MQTT 成为了最受欢迎的物联网协议&#xff0c;已广泛应用于车联网、智能家居、即时聊…

sqoop:错误: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster(已解决)

1 报错信息 错误: 找不到或无法加载主类 org.apache.hadoop.mapreduce.v2.app.MRAppMaster 说明&#xff1a; 操作将数据库中的数据导入到HDFS中 执行sqoop import --connect jdbc:mysql://aaa01:3306/mysql --username root --password root --table test 时报了以下错误 2 报…

遥控小车电子方案

遥控小车的功能开发主要包括以下几个方面&#xff1a; 1.基本功能开发&#xff1a; 前进、后退、左转、右转&#xff1a;通过遥控器上的控制按钮&#xff0c;实现小车的前进、后退、左转和右转。加速、减速&#xff1a;通过遥控器上的油门控制按钮&#xff0c;实现小车的加速…

【深度学习】Fine-Grained Face Swapping via Regional GAN Inversion高保真换脸范式

文章目录 代码介绍实践效果 帮助、问询 代码 https://github.com/e4s2022/e4s 介绍 Fine-Grained Face Swapping via Regional GAN Inversion 提出一种新的高保真换脸范式&#xff0c;能够保留期望的微妙几何和纹理细节。从微观面部编辑的角度重新思考换脸任务&#xff0c;基…

Matlab 实时读取串口并绘图

Matlab 实时读取串口并绘图 Vofa Vofa 是一个很好的跨平台上位机软件&#xff0c;但是它无法保存数据&#xff0c;而且作者也并没有要继续更新的意思&#xff0c;保存数据功能应该是遥遥无期了。因此本文使用 Matlab 实时读取串口数据&#xff0c;并使用 plot 函数绘制。 vo…

洛谷P1305 新二叉树

Java 代码 import java.util.Scanner;public class Main {public static void main(String[] args) {Scanner sc new Scanner(System.in);int n sc.nextInt();char arr[][] new char[n][3];for (int i 0; i < n; i) {String strsc.next();char arr1[]str.toCharArray()…

Linux学习-网络UDP

网络 数据传输,数据共享 网络协议模型 OSI协议模型 应用层 实际发送的数据 表示层 发送的数据是否加密 会话层 是否建立会话连接 传输层 数据传输的方式&#xff08;数据报、流式&#…

hexo接入github Discussions评论系统

评论存储仓 可以是你的博客项目的(github)仓库&#xff0c;也可以单独新建一个评论存储仓库。 我的博客项目在gitee上&#xff0c;就以新建存储仓为例&#xff1a; 使用Discussions评论系统必须开通Discussions模块&#xff01; 安装giscus插件 https://github.com/apps/…

如何在香橙派AIpro开发板升级CANN软件包

香橙派AIpro开发板是香橙派联合昇腾精心打造的高性能AI开发板&#xff0c;开发者可以基于昇腾CANN软件栈能力&#xff0c;快速构建AI应用和业务&#xff0c;实现图像、视频等多种数据分析与推理计算。在之前的文章中&#xff0c;我们已经了解了如何搭建开发环境&#xff0c;并基…

通过调用Vcenter-Api获取Vcenter中服务器信息

通过调用Vcenter-Api获取Vcenter中服务器信息 文章目录 通过调用Vcenter-Api获取Vcenter中服务器信息1. 获取Vmware API帮助文档2. 获取访问凭证3. 获取服务器清单4. 获取服务器更多信息5. 获取虚机更多信息6. 获取磁盘信息7. 获取操作系统相关 1. 获取Vmware API帮助文档 htt…

SHAP安装问题

一、安装 pip install shap -i https://pypi.tuna.tsinghua.edu.cn/simple 二、遇到问题 1、提示报错如下&#xff1a; ModuleNotFoundError: No module named numba.core 安装numba&#xff1a; pip install numba -i https://pypi.tuna.tsinghua.edu.cn/simple 提示已经…

FPGA核心板在声呐系统中的应用

前言 声纳系统使用声脉冲来探测、识别和跟踪水下物体。一个完整的声纳系统是由一个控制和显示部件、一个发射器电路、一个接收器电路和同时能作为发射装置&#xff08;扬声器&#xff09;和探测装置&#xff08;高灵敏度麦克风&#xff09;的传感器组成。 声纳系统图 技术挑战…