返回顶部
首页 > 资讯 > 后端开发 > Python >快速掌握用python写并行程序
  • 525
分享到

快速掌握用python写并行程序

快速程序python 2023-01-30 22:01:59 525人浏览 安东尼

Python 官方文档:入门教程 => 点击学习

摘要

目录 一、大数据时代的现状 二、面对挑战的方法 2.1 并行计算 2.2 改用GPU处理计算密集型程序

目录

  • 一、大数据时代的现状
  • 二、面对挑战的方法
    • 2.1 并行计算
  • 2.2 改用GPU处理计算密集型程序
  • 三、用python写并行程序
    • 3.1 进程与线程
    • 3.2 全局解释器GIL:
    • 3.3 multiprocessing
  • 四、multiprocessing实战
  • 总结

小子今天想来谈谈“并行计算”,作为一个非科班人员,我为什么去捣鼓这么一个在科班里也比较专业的问题了。这就要说下我前几天做的一个作业了,当时我用Python写了个程序,结果运行了一天,这个速度可让我愁了,我还怎么优化,怎么交作业啊。于是小子就去各大论坛寻丹问药了,终于让我发现可以用并行计算来最大化压榨电脑的CPU,提升计算效率,而且python里有multiprocessing这个库可以提供并行计算接口,于是小子花1天时间改进程序,终于在规定时间内做出了自己满意的结果,上交了作业。之后,小子对并行计算充满了兴趣,于是又重新在Google上游历了一番,大致弄清了GPU、CPU、进程、线程、并行计算、分布式计算等概念,也把python的multiprocessing耍了一遍,现在小子也算略有心得了,所以来此立碑,以示后来游客。
小子本文分为四部分,一是大数据时代现状,其二是面对挑战的方法,然后是用python写并行程序,最后是multiprocessing实战。

一、大数据时代的现状

当前我们正处于大数据时代,每天我们会通过手机、电脑等设备不断的将自己的数据传到互联网上。据统计,YouTube上每分钟就会增加500多小时的视频,面对如此海量的数据,如何高效的存储与处理它们就成了当前最大的挑战。
但在这个对硬件要求越来越高的时代,CPU却似乎并不这么给力了。自2013年以来,处理器频率的增长速度逐渐放缓了,目前CPU的频率主要分布在3~4GHz。这个也是可以理解的,毕竟摩尔定律都生效了50年了,如果它老人家还如此给力,那我们以后就只要静等处理器频率提升,什么计算问题在未来那都不是话下了。实际上CPU与频率是于能耗密切相关的,我们之前可以通过加电压来提升频率,但当能耗太大,散热问题就无法解决了,所以频率就逐渐稳定下来了,而Intel与AMD等大制造商也将目标转向了多核芯片,目前普通桌面PC也达到了4~8核。

二、面对挑战的方法

咱们有了多核CPU,以及大量计算设备,那我们怎么来用它们应对大数据时代的挑战了。那就要提到下面的方法了。

2.1 并行计算

并行(parallelism)是指程序运行时的状态,如果在同时刻有多个“工作单位”运行,则所运行的程序处于并行状态。图一是并行程序的示例,开始并行后,程序从主线程分出许多小的线程并同步执行,此时每个线程在各个独立的CPU进行运行,在所有线程都运行完成之后,它们会重新合并为主线程,而运行结果也会进行合并,并交给主线程继续处理。

多线程并行(OpenMap)

图一、多线程并行

图二是一个多线程的任务(沿线为线程时间),但它不是并行任务。这是因为task1与task2总是不在同一时刻执行,这个情况下单核CPU完全可以同时执行task1与task2。方法是在task1不执行的时候立即将CPU资源给task2用,task2空闲的时候CPU给task1用,这样通过时间窗调整任务,即可实现多线程程序,但task1与task2并没有同时执行过,所以不能称为并行。我们可以称它为并发(concurrency)程序,这个程序一定意义上提升了单个CPU的使用率,所以效率也相对较高。
并发程序

图二、多线程并发

并行编程模型:
  • 数据并行(Data Parallel)模型:将相同的操作同时作用于不同数据,只需要简单地指明执行什么并行操作以及并行操作对象。该模型反映在图一中即是,并行同时在主线程中拿取数据进行处理,并线程执行相同的操作,然后计算完成后合并结果。各个并行线程在执行时互不干扰。
  • 消息传递(Message Passing)模型:各个并行执行部分之间传递消息,相互通讯。消息传递模型的并行线程在执行时会传递数据,可能一个线程运行到一半的时候,它所占用的数据或处理结果就要交给另一个线程处理,这样,在设计并行程序时会给我们带来一定麻烦。该模型一般是分布式内存并行计算机所采用方法,但是也可以适用于共享式内存的并行计算机。

什么时候用并行计算:

  1. 多核CPU——计算密集型任务。尽量使用并行计算,可以提高任务执行效率。计算密集型任务会持续地将CPU占满,此时有越多CPU来分担任务,计算速度就会越快,这种情况才是并行程序的用武之地。
  2. 单核CPU——计算密集型任务。此时的任务已经把CPU资源100%消耗了,就没必要使用并行计算,毕竟硬件障碍摆在那里。
  3. 单核CPU——I/O密集型任务。I/O密集型任务在任务执行时需要经常调用磁盘、屏幕、键盘等外设,由于调用外设时CPU会空闲,所以CPU的利用率并不高,此时使用多线程程序,只是便于人机交互。计算效率提升不大。
  4. 多核CPU——I/O密集型任务。同单核CPU——I/O密集型任务。

2.2 改用GPU处理计算密集型程序

GPU即图形处理器核心(Graphics Processing Unit),它是显卡的心脏,显卡上还有显存,GPU与显存类似与CPU与内存。
GPU与CPU有不同的设计目标,CPU需要处理所有的计算指令,所以它的单元设计得相当复杂;而GPU主要为了图形“渲染”而设计,渲染即进行数据的列处理,所以GPU天生就会为了更快速地执行复杂算术运算和几何运算的。
GPU相比与CPU有如下优势:

  1. 强大的浮点数计算速度。
  2. 大量的计算核心,可以进行大型并行计算。一个普通的GPU也有数千个计算核心。
  3. 强大的数据吞吐量,GPU的吞吐量是CPU的数十倍,这意味着GPU有适合的处理大数据。

GPU目前在处理深度学习上用得十分多,英伟达(NVIDIA)目前也花大精力去开发适合深度学习的GPU。现在上百层的神经网络已经很常见了,面对如此庞大的计算量,CPU可能需要运算几天,而GPU却可以在几小时内算完,这个差距已经足够别人比我们多打几个比赛,多发几篇论文了。

3.3 分布式计算

说到分布式计算,我们就先说下下Google的3篇论文,原文可以直接点链接去下载:

  • GFS(The Google File System):解决数据存储的问题。采用N多台廉价的电脑,使用冗余的方式,来取得读写速度与数据安全并存的结果。
  • mapReduce(Simplified Data Processing on Large Clusters):函数式编程,把所有的操作都分成两类,map与reduce,map用来将数据分成多份,分开处理,reduce将处理后的结果进行归并,得到最终的结果。
  • BigTable(Bigtable: A Distributed Storage System for Structured Data):在分布式系统上存储结构化数据的一个解决方案,解决了巨大的Table的管理、负载均衡的问题.

Google在2003~2006年发表了这三篇论文之后,一时之间引起了轰动,但是Google并没有将MapReduce开源。在这种情况下hadoop就出现了,Doug Cutting在Google的3篇论文的理论基础上开发了Hadoop,此后Hadoop不断走向成熟,目前Facebook、IBM、ImageShack等知名公司都在使用Hadoop运行他们的程序。

分布式计算的优势:
可以集成诸多低配的计算机(成千上万台)进行高并发的储存与计算,从而达到与超级计算机媲美的处理能力。

三、用python写并行程序

在介绍如何使用python写并行程序之前,我们需要先补充几个概念,分别是进程、线程与全局解释器锁(Global Interpreter Lock, GIL)。

3.1 进程与线程

进程(process):

  • 在面向线程设计的系统(如当代多数操作系统linux 2.6及更新的版本)中,进程本身不是基本运行单位,而是线程的容器
  • 进程拥有自己独立的内存空间,所属线程可以访问进程的空间。
  • 程序本身只是指令、数据及其组织形式的描述,进程才是程序的真正运行实例。 例如,Visual Studio开发环境就是利用一个进程编辑源文件,并利用另一个进程完成编译工作的应用程序。

线程(threading):

  • 线程有自己的一组CPU指令、寄存器与私有数据区,线程的数据可以与同一进程的线程共享。
  • 当前的操作系统是面向线程的,即以线程为基本运行单位,并按线程分配CPU。

进程与线程有两个主要的不同点,其一是进程包含线程,线程使用进程的内存空间,当然线程也有自己的私有空间,但容量小;其二是进程有各自独立的内存空间,互不干扰,而线程是共享内存空间。
图三展示了进程、线程与CPU之间的关系。在图三中,进程一与进程二都含有3个线程,CPU会按照线程来分配任务,如图中4个CPU同时执行前4个线程,后两个标红线程处于等待状态,在CPU运行完当前线程时,等待的线程会被唤醒并进入CPU执行。通常,进程含有的线程数越多,则它占用CPU的时间会越长。


图三、进程、线程与CPU关系

3.2 全局解释器锁GIL:

GIL是计算机程序设计语言解释器用于同步线程的一种机制,它使得任何时刻仅有一个线程在执行。即便在多核心处理器上,使用 GIL 的解释器也只允许同一时间执行一个线程。Python的Cpython解释器(普遍使用的解释器)使用GIL,在一个Python解释器进程内可以执行多线程程序,但每次一个线程执行时就会获得全局解释器锁,使得别的线程只能等待,由于GIL几乎释放的同时就会被原线程马上获得,那些等待线程可能刚唤醒,所以经常造成线程不平衡享受CPU资源,此时多线程的效率比单线程还要低下。在python的官方文档里,它是这样解释GIL的:

In CPython, the global interpreter lock, or GIL, is a mutex that prevents multiple native threads from executing Python bytecodes at once. This lock is necessary mainly because CPython’s memory management is not thread-safe. (However, since the GIL exists, other features have grown to depend on the guarantees that it enforces.)

可以说它的初衷是很好的,为了保证线程间的数据安全性;但是随着时代的发展,GIL却成为了python并行计算的最大障碍,但这个时候GIL已经遍布CPython的各个角落,修改它的工作量太大,特别是对这种开源性的语音来说。但幸好GIL只锁了线程,我们可以再新建解释器进程来实现并行,那这就是multiprocessing的工作了。

3.3 multiprocessing

multiprocessing是python里的多进程包,通过它,我们可以在python程序里建立多进程来执行任务,从而进行并行计算。官方文档如下所述:

The multiprocessing package offers both local and remote concurrency, effectively side-stepping the Global Interpreter Lock by using subprocesses instead of threads.
我们接下来介绍下multiprocessing的各个接口:

3.3.1 进程process

multiprocessing.Process(target=None,  args=())
    target: 可以被run()调用的函数,简单来说就是进程中运行的函数
    args: 是target的参数

process的方法:
    start(): 开始启动进程,在创建process之后执行
    join([timeout]):阻塞目前父进程,直到调用join方法的进程执行完或超时(timeout),才继续执行父进程
    terminate():终止进程,不论进程有没有执行完,尽量少用。

示例1

from multiprocessing import Process

def f(name):
    print 'hello', name

if __name__ == '__main__':
    p = Process(target=f, args=('bob',)) # p进程执行f函数,参数为'bob',注意后面的“,”
    p.start() # 进程开始
    p.join() # 阻塞主线程,直至p进程执行结束

3.3.2 进程池Process Pools

class multiprocessing.Pool([processes])
    processes是进程池中的进程数,默认是本机的cpu数量
方法:
    apply(func[, args[, kwds]])进程池中的进程进行func函数操作,操作时会阻塞进程,直至生成结果。
    apply_async(func[, args[, kwds[, callback]]])与apply类似,但是不会阻塞进程
    map(func, iterable[, chunksize])进程池中的进程进行映射操作
    map_async(func, iterable[, chunksize[, callback]])
    imap(func, iterable[, chunksize]):返回有序迭代器
    imap_unordered(func, iterable[, chunsize]):返回无序迭代器
    close():禁止进程池再接收任务
    terminate():强行终止进程池,不论是否有任务在执行
    join():在close()或terminate()之后进行,等待进程退出

示例2

from multiprocessing import Pool

def f(x):
    return x*x

if __name__ == '__main__':
    p = Pool(5) # 创建有5个进程的进程池
    print(p.map(f, [1, 2, 3])) # 将f函数的操作给进程池

3.3.3 Pipes & Queues

multiprocessing.Pipe([duplex])
    返回两个连接对象(conn1, conn2),两个连接对象分别访问pipe的头和尾,进行读写操作
    Duplex: True(default),创建的pipe是双向的,也即两端都可以进行读写;若为False,则pipe是单向的,仅可以在一端读,另一端写,此时与Queue类似。

multiprocessing.Queue([maxsize])
    qsize():返回queue中member数量
    empty():如果queue是空的,则返回true
    full():如果queue中member数量达到maxsize,则返回true
    put(obj):将一个object放入到queue中
    get():从队列中取出一个object并将它从queue中移除,FIFO原则
    close():关闭队列,并将缓存的object写入pipe

示例

from multiprocessing import Pool
import time
def f(x):
    return x*x
if __name__ == '__main__':
    pool = Pool(processes=4)              # start 4 worker processes
    result = pool.apply_async(f, (10,))   # evaluate "f(10)" asynchronously in a single process
    print result.get(timeout=1)           # prints "100" unless your computer is *very* slow
    print pool.map(f, range(10))          # prints "[0, 1, 4,..., 81]"
    it = pool.imap(f, range(10))
    print it.next()                       # prints "0"
    print it.next()                       # prints "1"
    print it.next(timeout=1)              # prints "4" unless your computer is *very* slow
    result = pool.apply_async(time.sleep, (10,))
    print result.get(timeout=1)           # raises multiprocessing.TimeoutError

3.3.4 进程锁multiprocessing.Lock

当一个进程获得(acquire)锁之后,其它进程在想获得锁就会被禁止,可以保护数据,进行同步处理。
     acquire(block=True, timeout=None):尝试获取一个锁,如果block为true,则会在获得锁之后阻止其它进程再获取锁。
     release():释放锁

3.3.5 共享内存——Value, Array

共享内存通常需要配合进程锁来处理,保证处理的顺序相同。

multiprocessing.Value(typecode_or_type, *args[, lock])
    返回一个ctype对象,
    创建c = Value(‘d’, 3.14),调用c.value()
multiprocessing.Array(typecode_or_type, size_or_initializer, *, lock=True)
    返回一个ctype数组,只能是一维的
    Array(‘i’, [1, 2, 3, 4])
Type code C Type Python Type Minimum size in bytes
'b' signed char int 1
'B' unsigned char int 1
'u' Py_UNICODE Unicode character 2
'h' signed short int 2
'H' unsigned short int 2
'i' signed int int 2
'I' unsigned int int 2
'l' signed long int 4
'L' unsigned long int 4
'q' signed long long int 8
'Q' unsigned long long int 8
'f' float float 4
'd' double float 8

3.3.6 其它方法

multiprocessing.active_children():返回当前进程的所有子进程
multiprocessing.cpu_count():返回本计算机的cpu数量
multiprocessing.current_process():返回当前进程

3.3.7 注意事项:

  1. 尽量避免共享数据
  2. 所有对象都尽量是可以pickle的
  3. 避免使用terminate强行终止进程,以造成不可预料的后果
  4. 有队列的进程在终止前队列中的数据需要清空,join操作应放到queue清空后
  5. 明确给子进程传递资源、参数

windows平台另需注意:

  • 注意跨模块全局变量的使用,可能被各个进程修改造成结果不统一
  • 主模块需要加上if name == 'main':来提高它的安全性,如果有交互界面,需要加上freeze_support()

四、multiprocessing实战

process、lock与value尝试:

import multiprocessing as mp
import time

def job(v, num, l):
    l.acquire() # 锁住
    for _ in range(5):
        time.sleep(0.1) 
        v.value += num # 获取共享内存
        print(v.value)
    l.release() # 释放


def multicore():
    l = mp.Lock() # 定义一个进程锁
    #l = 1
    v = mp.Value('i', 0) # 定义共享内存
    p1 = mp.Process(target=job, args=(v,1,l)) # 需要将lock传入
    p2 = mp.Process(target=job, args=(v,3,l)) 
    p1.start()
    p2.start()
    p1.join()
    p2.join()

if __name__=='__main__':
    multicore()

上述代码即对共享内存叠加5次,p1进程每次叠加1,p2进程每次叠加3,为了避免p1与p2在运行时抢夺共享数据v,在进程执行时锁住了该进程,从而保证了执行的顺序。我测试了三个案例:

  1. 直接运行上述代码输出[1, 2, 3, 4, 5, 8, 11, 14, 17, 20],运行时间为1.037s
  2. 在1的基础上注释掉锁(上述注释了三行),在没有锁的情况下,输出[1, 4, 5, 8, 9, 12, 13, 15, 14, 16],运行时间为0.53s
  3. 在2的基础上将p1.join()调到p2.start()前面,输出为[1, 2, 3, 4, 5, 8, 11, 14, 17, 20],运行时间为1.042s.

可以发现,没锁的情况下调整join可以取得与加锁类似的结果,这是因为join即是阻塞主进程,直至当前进程结束才回到主进程,若将p1.join()放到p1.start()后面,则会马上阻塞主进程,使得p2要稍后才开始,这与锁的效果一样。
如果如上述代码所示,p1.join()在p2.start()后面,虽然是p1先join(),但这时只是阻塞了主进程,而p2是兄弟进程,它已经开始了,p1就不能阻止它了,所以这时如果没锁的话p1与p2就是并行了,运行时间就是一半,但因为它们争抢共享变量,所以输出就变得不确定了。

pool

import multiprocessing as mp
#import pdb

def job(i):
    return i*i

def multicore():
    pool = mp.Pool()
    #pdb.set_trace()
    res = pool.map(job, range(10))
    print(res)
    res = pool.apply_async(job, (2,))
    # 用get获得结果
    print(res.get())
    # 迭代器,i=0时apply一次,i=1时apply一次等等
    multi_res = [pool.apply_async(job, (i,)) for i in range(10)]
    # 从迭代器中取出
    print([res.get() for res in multi_res])

multicore()

pool其实非常好用,特别是map与apply_async。通过pool这个接口,我们只有指定可以并行的函数与函数参数列表,它就可以自动帮我们创建多进程池进行并行计算,真的不要太方便。pool特别适用于数据并行模型,假如是消息传递模型那还是建议自己通过process来创立进程吧。

总结

小子这次主要是按自己的理解把并行计算理了下,对进程、线程、CPU之间的关系做了下阐述,并把python的multiprocessing这个包拎了拎,个人感觉这个里面还大有学问,上次我一个师兄用python的process来控制单次迭代的运行时间(运行超时就跳过这次迭代,进入下一次迭代)也是让我涨了见识,后面还要多多学习啊。
感谢您花费宝贵的时间阅读到这里,希望能有所收获,也欢迎在评论区进行交流。

推荐好文:
multiprocessing官方文档
python多进程的理解 multiprocessing Process join run(推荐好文)
多进程 Multiprocessing

--结束END--

本文标题: 快速掌握用python写并行程序

本文链接: https://www.lsjlt.com/news/180174.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

猜你喜欢
  • 快速掌握用python写并行程序
    目录 一、大数据时代的现状 二、面对挑战的方法 2.1 并行计算 2.2 改用GPU处理计算密集型程序 ...
    99+
    2023-01-30
    快速 程序 python
  • 如何快速掌握Python协程
    这篇文章主要讲解了“如何快速掌握Python协程”,文中的讲解内容简单清晰,易于学习与理解,下面请大家跟着小编的思路慢慢深入,一起来研究和学习“如何快速掌握Python协程”吧! 1. 协程相关的概念1.1 进程和线程进程(Pro...
    99+
    2023-06-15
  • 快速掌握java排序算法-快速排序(图文)
    概念快速排序属于交换排序,主要步骤是使用基准元素进行比较,把小于基准元素的移动到一边,大于基准元素的移动到另一边。从而把数组分成两部分,然后再从这两部分中选取出基准元素,重复上面的步骤。过程如下:(推荐视频:java视频教程) 紫色:基准...
    99+
    2017-05-20
    java教程 快速排序 算法
  • 快速掌握PyCharm的运行快捷键
    PyCharm是一款功能强大的Python集成开发环境,通过灵活的快捷键可以提高开发效率。本文将向您介绍PyCharm中常用的运行快捷键,并提供具体的代码示例,帮助您快速入门PyCha...
    99+
    2024-02-26
    运行 pycharm 快捷键 python程序
  • PyCharm教程:快速掌握自动换行功能
    PyCharm是一款功能强大的Python集成开发环境,其自动换行功能可以帮助开发者更加高效地编写代码。本文将介绍如何快速掌握PyCharm中的自动换行功能,并提供具体的代码示例。 一...
    99+
    2024-02-23
    教程 pycharm 换行
  • 掌握 CPython 优化:让你的 Python 程序飞速运行
    ...
    99+
    2024-04-02
  • mybatis快速上手并运行程序
    1.Mybatis概述         MyBatis 是一款优秀的持久层框架,它支持自定义 SQL、存储过程以及高级映射。MyBatis 免除了几乎所有的 JDBC 代码以及设置参...
    99+
    2024-04-02
  • 掌握Python控制流程:编写高效程序
    控制流程是 Python 编程中至关重要的部分,它允许您控制程序的执行流。掌握控制流程对于编写高效、清晰且可维护的代码至关重要。 条件语句 Python 提供了多种条件语句来评估条件并根据结果执行不同代码块。这些语句包括: if-eli...
    99+
    2024-03-13
    控制流程
  • 快速掌握VueRouter使用方法
    目录一、编程式路由导航二、缓存路由组件三、两个新的声明周期钩子四、路由守卫五、路由器的两种工作模式本篇博客会介绍Vue中的VueRouter的基本使用,编程式路由导航增加了我们进行路...
    99+
    2023-01-09
    Vue Router用法 Vue Router原理
  • 怎么快速掌握Python基础语法
    本篇内容主要讲解“怎么快速掌握Python基础语法”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“怎么快速掌握Python基础语法”吧!  一、python编码  默认情况下, Python 源码...
    99+
    2023-06-02
  • Python中快速掌握Data Frame的常用操作
    目录掌握Data Frame的常用操作一. 查看DataFrame的常用属性 二. 查改增删DataFrame数据三. 描述分析DataFrame数据 掌握Data Frame的常用...
    99+
    2024-04-02
  • 如何快速掌握 Python 并发编程技术:npm 学习笔记分享!
    Python 并发编程技术是现代编程必备的技能之一。随着计算机硬件的不断发展,处理器核心数的增加,使得并发编程变得越来越重要。而 Python 作为一门简单易学的编程语言,也提供了丰富的并发编程技术。本文将介绍如何快速掌握 Python 并...
    99+
    2023-07-25
    npm 学习笔记 并发
  • 快速掌握MySQL基础教程方法
    本文主要给大家介绍快速掌握MySQL基础教程方法,文章内容都是笔者用心摘选和编辑的,具有一定的针对性,对大家的参考意义还是比较大的,下面跟笔者一起了解下快速掌握MySQL基础教程方法吧。1分钟安装Part1...
    99+
    2024-04-02
  • JS快速掌握ES6的class用法
    1.如何构造? 先复习一下es5常用的构建类的方法:首先es5的写法使用原型进行对象的方法的,为什么不在构造函数里添加方法呢?因为实例化对象的时候,会重复的建立好多相同的方法,浪费资...
    99+
    2024-04-02
  • 快速掌握Python教程:如何使用git来load你的工程?
    Python是一种高级编程语言,它被广泛用于各种领域,如数据分析、人工智能、Web开发等。而git则是一种版本控制工具,它可以帮助开发者更好地管理代码,协同开发。 在Python开发中,使用git来load你的工程是非常必要的。本文将介绍如...
    99+
    2023-06-26
    教程 load git
  • Python、Django、npm 教程:如何快速掌握这些工具?
    Python、Django、npm 都是现代化的编程工具,在开发过程中都有着重要的作用。Python 是一种高级编程语言,可以用于各种目的,包括 Web 开发、科学计算、人工智能等。Django 是一个流行的 Python Web 开发框...
    99+
    2023-10-30
    django npm 教程
  • 掌握 Python asyncio:揭示并行编程的秘密
    前言 asyncio 是 Python 中一种强大的工具,它允许开发人员编写异步代码,从而在不阻塞主线程的情况下处理多个并发任务。本文将深入探讨 asyncio 的工作原理,演示其使用方法,并提供代码示例以帮助理解其概念。 asyncio...
    99+
    2024-03-03
    asyncio Python 并行编程 异步编程
  • 如何快速掌握Python的基础知识
    本篇内容主要讲解“如何快速掌握Python的基础知识”,感兴趣的朋友不妨来看看。本文介绍的方法操作简单快捷,实用性强。下面就让小编来带大家学习“如何快速掌握Python的基础知识”吧!python函数函数通过def关键字定义,形如pytho...
    99+
    2023-06-27
  • 快速掌握运用Python中len函数的技巧
    快速掌握Python中len函数的使用技巧,需要具体代码示例 Python是一种简洁、易读的编程语言,广泛应用于数据科学、机器学习、网络开发等领域。在Python中,len函数是一个非常常用且重要的函数之一。它用于返回一个对象(...
    99+
    2024-01-29
    Python 使用技巧 len函数
  • 快速掌握 PHP、Linux 和 NPM:完整教程
    PHP、Linux 和 NPM 是现代 Web 开发中必不可少的工具。PHP 作为一种流行的服务器端编程语言,让开发人员可以轻松构建动态 Web 应用程序。Linux 作为一种开源操作系统,为开发人员提供了一个高度可定制和可扩展的平台。而 ...
    99+
    2023-11-04
    linux npm 教程
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作