Python的高级并发技术

Python高级核心技术解析:内存管理、并发编程与元编程实战 Python作为一门高级编程语言,其内存管理机制基于引用计数和垃圾回收原理,通过自动内存管理技术价值在于简化开发复杂度。在实际应用场景中,开发者需要深入理解全局解释器锁(GIL)对并发编程的影响,以及异步IO如何提升I/O密集型任务性能。元编程作为Python的高级特性,通过装饰器和描述符协议实现代码的动态修改,在框架开发和性能优化中发挥重要作用。本文聚焦Python内存管理与垃圾回收机制,结合循环引用和弱引用等热词,系统讲解Python高级编程核心技术。 阅读详情

与“非并发的程序”(nonconcurrent program)相比,并发程序更难编写,也更难维护(有时甚至难度相当大),而且并发程序的运行效率有时比非并发的程序低(甚至低得多)。虽然如此,但优秀的并发程序确实比非并发程序快很多,所以,为了提高效率,我们还是得花时间去研究它。

目前大多数编程语言(包括C++和Java)都直接支持并发,而且其标准库通常还提供了一些封装程度较高的功能。并发可以通过多种方式来实现,这些方式之间最重要的区别在于如何访问“共享数据(shared data)”:是通过“共享内存”(shared memory)等方式直接访问,还是通过“进程间通信”(Inter-Process Communication,IPC)等方式间接访问。“基于线程的并发”(threaded concurrency)是指同一个系统进程里有各自独立的若干个线程,它们都在并发执行任务。这些线程一般会依序访问共享内存,以此实现数据共享。程序员通常采用某种“锁定机制”(locking mechanism)来确保同一时间只有一个线程能够访问数据。“基于进程的并发”(process-based concurrency,或multiprocessing)是指多个进程独立地执行任务。这些进程一般通过IPC来访问共享数据,如果编程语言或程序库支持,那么也可以通过共享内存来实现数据共享。还有一种并发,它基于“并发等待”(concurrent waiting)而非“并发执行”(concurrent execution),这种方式通常用来实现异步I/O。

Python对异步I/O提供了某些底层支持(asyncore与asynchat模块)。Twisted框架则提供了高层支持。Python3.4计划将高层异步I/O功能(也包括事件循环)添加到Python标准库中。

刚才提到了两种传统的并发方式,也就是基于线程和基于进程的并发,这两种方式Python都支持。Python对多线程的支持方式相当普通,但对于多进程的支持方式则比大多数编程语言或程序库更为高级。此外,Python的多进程与多线程采用同一套机制,使得开发者很容易就能在两套方案中来回切换,至少在不使用共享内存是如此的。

由于有“全局解释器锁”(Global Interpreter Lock,GIL),所以Python解释器在同一时刻只能运行于一个处理器之中。Python基本上是用C语言写成的,个别标准库也是这样,而C语言代码是可以获取及释放GIL的,因此没有这样的限制。即便如此,想通过多线程并发来提高程序速度其效果可能仍然不够理想。

一般来说,计算密集型任务不适合用多线程实现,因为这样做通常比非并发程序还要慢。一种办法是改用Cython来编写代码,Cython代码实际上与Python一样,只是多加了一套写法,能够把程序编译成纯C。这样程序执行起来可以比原来快100倍,而用并发则很难达到这样的效果,因为其性能提升程度与处理器核心的数量成正比。如果碰到需要使用并发的场合,而所要执行的任务又是计算密集型的,那么最好避开GIL,改用multiprocessing模块。如果使用多线程,那么同一个进程里的线程在执行时会相互争抢GIL,但如果改用multiprocessing,那么每个进程都是独立的,它们都有自己的Python解释器实例,所以也就不会争抢GIL了。

对于网络通信等“I/O密集型”(I/O-bound)任务来说,并发可以大幅度提升程序执行速度。在这种情况下,决定程序效率的主要因素是网络延迟,这与线程还是进程来实现并发可能并没有多大关系。

并发级别 
* 低级并发(Low-Level Concurrency,底层并发):就是直接用“原子操作”(atomicoperation)所实现的并发。这种并发是给程序库的编写者用的,而应用程序的开发者则不需要它,因为这种写法很容易出错,而且极难调试。虽说Python本身的并发机制一般是用底层操作实现出来的,但开发者不能用Python语言编写这种级别的并发代码。 
* 中级并发(Mid-Level Concurrency):不直接使用原子操作,但却会直接使用“锁”(lock),大多数语言提供的都是这种级别的并发。Python的threading.Semaphore,threading.Lock,及multiprocessing.Lock等类都支持中级并发。开发应用程序的人一般会使用中级并发,因为他们通常只能使用这个级别的开发功能。 
* 高级并发(High-Level Concurrency):既不直接使用原子操作,也不直接使用锁。(锁和原子操作可能在幕后使用,但开发者无须关系这些。)目前已经有编程语言开始支持高级并发了。从3.2版本起,Python提供了支持高级并发的concurrent.futures模块,此外,queue.Queue及multiprocessing这两个“队列集合类”(queue collection class)也支持高级并发。

中级并发用起来虽然简单,但却很容易出错,尤其容易出现那种难于追踪而且调试起来非常麻烦的错误,此外还会导致程序莫名其妙地崩溃或“失去响应”(frozen)。

关键问题出在共享数据上面。如果共享数据可以修改,那么必须用锁保护起来,以确保所有线程或进程都要依序存取它(也就是说,同一个时刻只能有一个线程或进程访问这份数据)。如果多个线程或进程试图访问同一份共享数据,那么只有其中一个能够获取到,而其他的都会阻塞(也就是进入“空闲”(idle)状态)。这就意味着,当锁定机制生效时,应用程序中只能有一个线程或进程起作用(这就变得和非并发程序类似了),其余的都要得等待。由此可见,我们应当尽量少用锁,即便要用,也不要时间太长。最简单的办法是根本不要分享可以修改的数据,这样就可以不加锁了,而大部分并发问题也就随之消失了。

有些时候,多个并发的线程或进程确实需要访问同一份数据,但我们不必直接加锁即可解决此问题。一种办法是采用支持“并发访问”(concurrent access)的数据结构,queue模块提供了许多“能在多线程环境下安全使用的”(thread-safe, “线程安全的”)队列,如果是基于多进程开发,那么可以使用multiprocessing.JoinableQueue及multiprocessing.Queue类。前面这种队列能够统一存放待执行队列,以供并发线程或进程从中领取,后面那种队列则可用来收集任务的执行结果。在整个过程中,加锁操作都是由数据结果自身负责的。

上面这些支持并发的队列也许不适合用来表述我们所要操作的数据,在这种情况下,如果不想加锁,那么最好的办法就是传递“不可变的数据”(immutable data,比如数字或字符串),或者是传递“可变的数据”(mutable data),但却不修改它。假如一定要使用“可变的数据”,那么最安全的办法就是对其“深拷贝”(deep copy),这样可以免去因加锁而带来的开销和麻烦,不过,拷贝操作本身需要占用处理器和内存。另外,如果是多进程并发,那么可以使用支持并发访问的数据类型,特别是multiprocessing.Value与multiprocessing.Array,前者表示单个可变的值,而后者则是由可变的值所构成的数组,二者都需要通过multiprocessing.Manager来创建。

计算密集型并发

缩小图像是一种需要大量运算的操作,所以多进程技术应该能够最大程度地提升程序性能。

程序 并发 执行时间(秒) 速度倍数
imagescale-s.py 无 784 基准
imagescale-c.py 4个协程 781 1.00
imagescale-t.py 4个线程,使用线程池 1339 0.59
imagescale-q-m.py 4个进程,使用队列 206 3.81
imagescale-m.py 4个进程,使用进程池 201 3.90

imagescale-t.py程序使用了4个线程,其运行结果显然可以说明采用多线程来计算密集型任务的效率比非并发还要低。这是因为Python把所有处理任务放在了同一个核里,除了执行缩小操作之外,还要在四个线程之间进行“上下文切换”(context switching),这将产生大量开销。采用多进程队列和使用进程池的差别不大,两者都与我们所预估的速度相符(也就是说,速度与CPU的核心数成正比)。

所有图像缩小程序都接受命令行参数,我们用argparse来解析这些参数。所有版本都需要指定如下参数:缩小后的图像尺寸,是否使用平滑缩放,缩小前的图像所在的文件夹,缩小后的图像所在的文件夹。如果图像本身比指定的尺寸还小,那么就不缩小了,而是直接拷贝过去。采用并发的那几个版本还可以通过concurrency参数来指定程序所使用的线程或进程个数。该参数纯粹是为了调试和统计执行时间而设的。计算密集型程序所使用的线程或进程数量一般与CPU核心相同。I/O密级型程序会根据网络带宽状况使用核心数的倍数(比如2倍,3倍,4倍等)作为线程或进程的数量。

  1. def handle_commandline():
  2. parser = argparse.ArgumentParser()
  3. parser.add_argument('-c', '--concurrency', type=int,
  4. default=multiprocessing.cpu_conut(),
  5. help='specify the concurrency (for debuging and '
  6. 'timing) [default: %(default)d]')
  7. parser.add_argument('-s', '--size', default=400, type=int,
  8. help='make a scaled image that fits the given dimension [default: %(default)d]')
  9. parser.add_argument('-S', '--smooth', action='store_true',
  10. help='use smooth scaling (slow but good for text)')
  11. parser.add_argument('source',
  12. help='the directory containing the original .xpm images')
  13. parser.add_argument('target',
  14. help='the directory for the scaled .xpm images')
  15. args = parser.parse_args()
  16. source = os.path.abspath(args.source)
  17. target = os.path.abspath(args.target)
  18. if source == target:
  19. args.error("source and target must be different")
  20. if not os.path.abspath.exists(args.target):
  21. os.makedirs(target)
  22. return args.size, args.smooth, source, target, args.concurrency

应用程序一般都不会向用户提供并发选项,但它可以用于调试,统计执行时间,测试程序等。multiprocessing.cpu_count()函数返回计算机的核心数。

argparse模块采用“陈述式”(declarative)的方式来创建命令行解释器。创建好解释器之后,我们用它来解析命令行,并获取其中的参数,然后会简单地判断一些这些参数是否有效(例如,目标文件夹不得与源文件夹相同)。如果目标文件夹尚未建立,那么就新建一个。os.makedirs()函数与os.mkdir()类似,但后者只能在现存的文件夹下面新建子文件夹,而前者还可以自动创建子文件夹与现有的上层文件夹之间的那些文件夹。

用队列及多进程实现并发

imagescale-q-m.py程序创建了两个队列,一个用来保存待执行的任务(也就是待缩小的图像),另一个用来收集任务的执行结果。

  1. Result = collections.namedtuple('Result', 'copied scaled name')
  2. Sumary = collections.namedtuple('Summary', 'todo copied scaled canceled')

Result是个“具名元组”(named tuple),用来存放单张图片的处理结果。其中前两个元素表示拷贝及缩小过的图片数量,对于单张照片来说,这两个值要么是1,0,要么是0,1,第三个元素是缩小后的图片名称。Summary也是具名元组,用来汇总所有图片的处理结果。

  1. def main():
  2. size, smooth, source, target, concurrency = handle_commandline()
  3. Qtrac.report('starting...')
  4. summary = scale(size, smooth, source, target, concurrency)
  5. summarize(summary, concurrency)

所有图像缩小程序的main()函数都一样,它先用自编的handle_commandline()函数读出命令行参数。函数所返回的五个参数分别表示:缩小后的图像尺寸,是否采用平滑缩放,缩小前的图片所在目录,缩小后的图片所在目录以及程序所使用的线程或进程个数(只有并发版本才会用到这个参数,其默认值等于CPU的核心数)。

程序随后告诉用户,现在开始知晓能够图片缩小操作,然后调用scale()函数,全部任务都会在这个函数里完成。scale()函数会把执行结果汇总,并返回给调用者,我们用summarize()函数将其打印出来。

  1. def report(message='', error=False):
  2. if len(message) >= 70 and not error:
  3. message = message[:67] + '...'
  4. sys.stdout.write('\r{:70}{}'.format(message, '\n' if error else ''))
  5. sys.stdout.flush()

本章与开发相关的所有范例程序都要使用控制台,为了用起来方便一些,我们把report()函数放在了Qtrac.py模块里。该函数用message参数中的消息来覆写控制台当前这一行的文字(如果大于70个字符,那么就截取前67个),并调用flash()方法将其立刻打印到控制台里。如果message中的消息是错误信息,那么就在后面加上换行符,以防其他消息覆写此消息。report()函数不会将错误信息截断。

  1. def scale(size, smooth, source, target, concurrency):
  2. canceled = False
  3. jobs = multiprocessing.JoinableQueue()
  4. results = multiprocessing.Queue()
  5. create_processes(size, smooth, jobs, results, concurrency)
  6. todo = add_jobs(source, target, jobs)
  7. try:
  8. jobs.join()
  9. except KeyboardInterrupt: # May not work on Windows
  10. Qtrac.report('canceling...')
  11. canceled = True
  12. copied = scaled = 0
  13. while not results.empty(): # Scale because all jobs have finished
  14. result = results.get_nowait()
  15. copied += result.copied
  16. scaled += result.scaled
  17. return Summary(todo, copied, scaled, canceled)

本程序采用基于队列的多进程技术来实现并发式图像缩放,而上面这个函数则是程序的核心。函数首先创建了“joinable queue”(支持join()方法的队列),把待处理的任务放入其中。开发者可以在joinable queue上面调用join(),该方法会一直阻塞,知道任务队列变空后才返回。创建好这个队列之后,scale()函数又创建了一个nonjoinable queue,用于保存执行结果。接下来,创建缩小操作所需的进程,调用完create_processes()函数之后,这些进程就能够执行任务了,但目前它们尚处于阻塞状态,因为工作队列里还没有放入任务。然后,调用add_jobs()函数,把全部任务都添加到工作队列里。

把所有任务都放入队列之后,调用multiprocessing.JoinableQueue.join()方法,等队列变空。

所有任务都执行完(或用户取消了整个操作)之后,我们遍历results队列,以便统计计算结果。一般情况下,在并发队列上调用empty()方法所返回的结果是不可靠的,但此处却可以这么做,因为所有的工作进程都已经完工了。该队列的状态不会再改变了。我们在循环体里面调用multiprocessing.Queue.get_nowait()来获取执行结果,而没有像平时那样调用multiprocessing.Queue.get()方法,也是由于这个原因。

收集到所有任务的执行结果之后,我们把详细信息放在Summary具名元组里并返回给调用者。如果程序照常执行了全部任务,那么todo值是0,canceled值是False;如果任务取消了,那么todo值可能不是0,但canceled值会是True。

这个函数虽然名叫scale(),但却是个相当通用的“并发式任务执行”函数,它会把待执行的任务分派给各个进程,并收集执行结果。只需稍加改编,就能在其他场合使用。

  1. def create_processes(size, smooth, jobs, results, concurrency):
  2. for _ in range(concurrency):
  3. process = multiprocessing.Process(target=worker, args=(size, smooth, jobs, results))
  4. process.daemon = True
  5. process.start()

上面这个函数会创建许多进程,这些进程都可以执行任务。创建每个进程时,传入的都是同一个worker()函数(因为它们要执行的任务都是相同,就是缩小图像),此外还传入了任务的细节。细节信息里面包含两个共享任务队列,一个用于存放任务,另一个用于收集结果。开发者不需要手工给这些任务加锁,因为它们自己会处理同步问题。创建好进程之后,我们将其设为daemon(守护进程)。主进程终止后,所有守护进程也会照常终止(不是守护进程的那些进程还会继续运行,但是在Unix系统上,它们会变成“僵尸进程”(zombie process)。

create_processes()函数会创建好所有进程,并将它们设置成守护进程,每创建完一个进程,就会调用其start()方法,促使其开始执行worker()函数。这些进程此时必然都会阻塞,因为任务队列里面还没有任务。他们虽然阻塞了,但主进程很快就能把这些进程都创建完,并且从create_processes()函数中返回。然后,调用该函数的那段代码会把待处理的任务添加到队列里,于是,刚才那些阻塞的进程就可以领取任务,并继续往下执行了。

  1. def worker(size, smooth, jobs, results):
  2. while True:
  3. try:
  4. sourceImage, targetImage = jobs.get()
  5. try:
  6. result = scale_one(size, smooth, sourceIamge, targetImage)
  7. Qtrac.report('{} {}'.format('copied' if result.copied else 'scaled', os.path.basename(result.name)))
  8. results.put(result)
  9. except Image.Error as err:
  10. Qtrac.report(str(err), True)
  11. finally:
  12. jobs.task_done()

本来我们可以从multiprocessing.Process类(或threading.Thread类)中继承子类,然后用子类实例实现并发,但是却采用另一种办法,就是将任务封装在函数里,然后把函数经target参数传给multiprocessing.Process对象,这样会稍微简单一点(创建thread.Thread对象时,也可以这么做。)

worker()函数是个无限循环,每一轮都试着从共享的工作队列里领取一项任务。此外使用无限循环不会出问题,因为执行worker()函数的进程都是守护进程,当整个程序终止时,它们也会随之终止。如果队列里没有任务,那么multiprocessing.Queue.get()方法就会一直阻塞,等获取到任务之后,才会将其返回。返回的值是个二元组,在本例中,二元组的两个元素分别表示源图像和目标图像的名称。

领取任务之后,我们通过scale_one()函数来缩小(或拷贝)图像,并将操作结果告知用户。然后,把result对象(该对象的类型是Result)放到保存操作结果的共享队列里。

使用joinable queue的时候要注意:执行完其中的任务之后,一定要调用multiprocessing.JoinableQueue.task_done()方法。只有这样,multiprocessing.JoinableQueue.join()方法才能知道队列中的所有任务是不是都执行完了(也就是说,队列里是不是已经没有待执行的任务了)。

  1. def add_jobs(source, target, jobs):
  2. for todo, name in enumerate(os.listdir(source), start=1):
  3. sourceImage = os.path.join(source, name)
  4. targetImage = os.path.join(target, name)
  5. jobs.put((sourceImage, targetImage))
  6. return todo

创建并启动进程之后,它们就处于阻塞状态,所有进程都等着从共享的队列里领取任务。

add_jobs()函数会针对每张待处理的图像创建两个字符串:sourceImage表示源图像的完整路径,而targetImage则表示目标图像的完整路径。函数会把这两个字符串包在二元组里,添加到共享的工作队列中。最后,把待处理的任务数返回给调用者。

任务队列中有了第一个任务之后,原来处于阻塞状态的某个工作进程就会将其领取,并开始执行任务。最后,所有工作进程都能领到任务。在各进程执行任务时,工作队列也会有新的任务加进来,只要有进程执行完自己现有的任务,它就可以从队列中再领取一项新任务。这些进程最终会把队列中的任务都领走,它们执行完自己的任务之后,就会处于阻塞状态,程序终止时,这些进程也会随之终止。

  1. def scale_one(size, smooth, sourceImage, targetImage):
  2. oldImage = Image.from_file(sourceImage)
  3. if oldImage.width <= size and oldImage.height <= size:
  4. oldImage.save(targetImage)
  5. return Result(1, 0, targetImage)
  6. else:
  7. if smooth:
  8. scale = min(size / oldImage.width, size / oldImage.height)
  9. newImage = oldImage.scale(scale)
  10. else:
  11. stride = int(math.ceil(max(oldImage.width / size,
  12. oldImage.height / size)))
  13. newImage = oldImage.subsample(stride)
  14. newImage.save(targetImage)
  15. return Result(0, 1, targetImage)

上面这个函数负责执行实际的缩小(或拷贝)操作。它会优先考虑使用cyImage模块,若无法使用该模块,则使用Image模块。假如待处理的图像本身就比目标尺寸小,那么直接将其保存到targetImage就可以,此时函数会返回Result对象。构造该对象使传入的三个参数分别表示本次操作所拷贝的图像数量(1张),缩小的图像数量(0张)以及新图像的名称。如果待处理的图像比目标尺寸大,那么就通过oldImage对象的scale()方法或subsample()方法将其缩小,并把处理后的图像保存成新的图片。在这种情况下,也会返回Result对象,构造对象时,前两个参数的值会对调,表明本次操作没有拷贝图像,但是缩小了一张图像,第三个参数仍然是新图像的名称。

  1. def summarize(summary, concurrency):
  2. message = 'copied {} scaled {}'.format(summary.copied, summary.scaled)
  3. difference = summary.todo - (summary.copied + summary.scaled)
  4. if difference:
  5. message += 'skipped {}'.format(difference)
  6. message += 'using {} processes'.format(concurrency)
  7. if summary.canceled:
  8. message += ' [canceled]'
  9. Qtrac.report(message)
  10. print()

等所有图像都处理完(也就是队列的join()方法返回的时候),scale()函数会创建Summary对象,并将其传给summarize()函数。

Python高级编程核心技术:装饰器、元编程与并发编程实战指南 Python作为一门动态编程语言,其高级特性如装饰器和元编程构成了语言的核心机制。装饰器基于函数作为一等公民的原理,通过闭包实现功能增强,在日志记录、性能监控等场景中展现技术价值。元编程通过描述符协议和元类机制,为框架开发和API设计提供强大支持。在并发编程领域,理解GIL限制和asyncio事件循环原理,能够针对CPU密集型和IO密集型任务选择合适的并发策略。这些Python高级技术在实际工程实践中,特别是在性能优化和内存管理方面,帮助开发者构建高效可维护的应用系统。本文通过装饰器实现和元类应用等具体案例 阅读详情

相关推荐

Python高级特性实战:生成器、装饰器与并发编程核心技术解析

生成器作为Python内存优化的关键技术,通过yield关键字实现惰性计算,在处理大数据流时能显著降低内存占用。其原理是基于迭代器协议,在需要时按需生成数据而非一次性加载全部内容。这种技术价值在于解决IO密集型任务的内存瓶颈问题,广泛应用于文件处理、数据流分析和网络请求等场景。装饰器则通过高阶函数实现代码复用,结合元编程能力为函数添加额外功能,在Web开发、API设计和性能监控中发挥重要作用。理解这些Python高级特性有助于开发者编写更高效、可维护的企业级应用,自然过渡到本文对Python核心进阶技术的深

weixin_30820077的博客 445

The Python Tutorial 3.2-2使用Python解释器

2. Using the Python Interpreter(使用Python解释器) 2.1. Invoking the Interpreter(调用解释器) The Python interpreter is usually installed as /usr/local/bin/python3.2 on those machines where it is available; p

Lbeta成长记 1392

深入解析 Python 爬虫的高级反爬技术与大规模数据抓取

本文深入探讨了Python爬虫应对高级反爬技术和大规模数据抓取的解决方案。首先分析了动态验证码、JavaScript渲染、行为分析等常见反爬手段,并提供了验证码破解、Selenium模拟等应对方法。针对大规模抓取,介绍了IP代理轮换、分布式存储优化及并发爬取技术,包括Scrapy-Redis和asyncio实现方案。文章总结了高效抓取的最佳实践,强调通过代理池、分布式架构和合理存储选择来提升爬虫稳定性和效率,为开发者应对复杂反爬场景提供了系统指导。

专注于Python爬虫开发,分享爬虫技巧、项目实战与反爬经验,使用Scrapy、BeautifulSoup等工具,解决数据抓取难题。 1428

万字长文掌握Python高并发

高并发一直在软件开发遇到的老大难问题,软件承载并发的能力也是一个核心性能点之一,这篇文章主要讲解Python语言的高并发工具,主要包括多进程、多线程、协程等。同时聊聊python的全局解释器锁对多线程的影响。

kobe_okok的博客 4744

华为昇腾 910B 实战:DeepSeek-R1 蒸馏模型高效部署与性能调优全解析

本文详细解析了在华为昇腾910B硬件平台上高效部署DeepSeek-R1蒸馏系列模型(14B/32B版本)的完整实战流程。内容涵盖从MindIE环境搭建、镜像获取、模型准备,到服务配置、内存参数调优、性能测试及常见问题排查,为开发者提供了基于昇腾910B进行大模型部署与优化的全链路指南。

weixin_28235513的博客 210

RedHat 9 替换yum源镜像

引言:我们个人通常使用的红帽系统yum源是需要注册付费的,所以在使用yum源安装一些软件时无法正常安装(例如:MySQL),这时我们就需要将yum源替换为CentOS对应的源,以实现在红帽系统中正常安装软件。

YUJIAOZHU666的博客 3738

Python高并发原理与实战解决方案指南

高并发(High Concurrency)指系统在单位时间内能同时处理大量请求的能力,常见于Web服务、API接口、实时数据处理、典型场景如电商秒杀、实时聊天、API网关等场景。QPS(每秒查询率):系统每秒能处理的请求量响应时间:从请求发出到获得响应的延迟吞吐量**: 单位时间内的数据处理总量并发用户数:同时保持有效会话的用户数量5在Python中,由于**全局解释器锁(GIL)**的存在,传统多线程无法充分利用多核CPU性能,需要采用特殊技术手段实现高并发。

weixin_45145684的博客 1604

FTPClient使用中,碰到SocketTimeoutException 坑

ftpclient设置soTimeout无效

u010379794的博客 1951

Python -- 高并发的解决方案

并发基本概念并发和并行区别并行,parallel并发,concurrency举例并发的解决1、队列、缓冲区2、争抢3、预处理4、并行5、提速6、消息中间件 基本概念 并发和并行区别 并行,parallel 同时做某些事,可以互不干扰的同一个时刻做几件事 并发,concurrency 也是同时做某些事,但是强调,一个时段内有事情要处理。 举例 高速公路的车道,双向4车道,所有车辆(数据)可...

python_lqx的博客 1万+

区块链技术在碳足迹数据存证与溯源中的应用深度解析

消费者扫描产品上的二维码,即可通过区块链浏览器查询到该产品的数字碳标签,并追溯其从茶园到货架的每一步碳足迹数据,以及这些数据是如何被智能合约自动计算和认证的,从而建立起强大的品牌信任。如果说哈希链解决了数据的“存”与“证”的问题,那么智能合约则解决了数据“用”与“管”的自动化问题。综上所述,虽然针对“碳足迹数据可追溯性”这一特定应用场景的公开、标准化的性能基准案例尚不丰富,但现有研究和企业级解决方案(特别是联盟链)已经证明,通过合理的技术选型和架构设计,区块链的性能可以满足实际商业需求。

百态·数智思维 | 聚焦大数据、量化与未来AI 1106

零基础玩转STM32CubeIDE LL库:5分钟搞定串口通信(附完整代码)

本文为零基础开发者提供了一份STM32CubeIDE LL库串口通信的快速实战指南。通过CubeMX配置、LL库核心API详解,以及中断接收与环形缓冲区的完整代码实现,帮助读者在5分钟内搭建稳定可靠的串口收发框架,解决从HAL切换到LL库的常见困惑,提升嵌入式开发效率。

weixin_29159441的博客 306

chatgpt赋能python:如何使用Python实现高并发

高并发是指在同一时间内有大量的请求同时对服务器发出请求,这就需要服务器能够承受超出其正常承载能力的流量。如果服务器无法处理这种高流量,则可能会导致服务器崩溃或瘫痪的情况,这是我们不想看到的。本文由chatgpt生成,文章没有在chatgpt生成的基础上进行任何的修改。以上只是chatgpt能力的冰山一角。作为通用的Aigc大模型,只是展现它原本的实力。对于颠覆工作方式的ChatGPT,应该选择拥抱而不是抗拒,未来属于“会用”AI的人。🧡AI职场汇报智能办公文案写作效率提升教程 🧡专注于AI+职场+办公。

b45e1933f46的博客 432

《拉依达的嵌入式\驱动面试宝典》—C/CPP基础篇(二)

《拉依达的嵌入式\驱动面试宝典》 整合了所有我认为可能遇到的技术面试问题。所有问题及其答案均是我个人学习后查阅资料总结,每个回答都做了仔细的分析,在嵌入式及其驱动面试相关问题解析做到全网独一无二。学习或者转行到嵌入式、驱动开发领域学习的不二之选

拉依达不拉跨的博客 578

python多线程并发编程技术_并发编程技术 --Python高级

Python高级并发编程技术并发任务处理,即同时执行多个任务,可以采用如下几种方案实现:1.多进程,即创建多个进程,每个进程(其实是进程中的主线程)负责执行一个任务,由于多个进程可以同时运行,所以就可以实现并发任务处理2,多线程:即创建多个线程,每个线程负责执行一个任务,由于多个线程可以同时运行,所以就可以实现并发任务处理3.多进程+多线程,即创建多个进程,并且每个进程中创建多个线程进程(Proc...

weixin_26729841的博客 275

39、低功耗处理器性能评估与Cortex - M23/M33低功耗特性解析

本文深入解析了Cortex-M23和Cortex-M33处理器的低功耗特性及其性能评估方法。介绍了ULPMark、CoreMark、IoTMark-BLE和SecureMark-TLS等基准测试在能效评估中的应用,并详细阐述了处理器的睡眠模式、系统控制寄存器(SCR)配置、WFI/WFE指令、退出时睡眠、挂起时发送事件(SEVONPEND)以及唤醒中断控制器(WIC)等关键低功耗机制。结合状态保留技术,展示了如何通过芯片级设计大幅降低泄漏电流,实现高效能低功耗的物联网与嵌入式系统设计。

Pepper的专栏 130

路径规划 | 图解A*、Dijkstra、GBFS算法的异同(附C++/Python/Matlab仿真)

图解A*、Dijkstra、GBFS算法原理,分析三种算法异同,提供C++/Python/Matlab仿真实现

FRIGIDWINTER的博客 2万+

Python高级编程核心技术:并发、内存管理与性能优化实战

并发编程是现代软件开发的核心概念,通过多线程、多进程和异步编程等技术实现任务并行处理,提升程序执行效率。其原理基于操作系统调度和事件循环机制,能够有效利用多核CPU资源。在Python高级编程中,并发技术价值体现在处理高并发网络服务、大数据分析等I/O密集型场景时显著提升吞吐量。应用场景涵盖Web后端开发、API服务、数据处理等需要高性能响应的领域。本文重点探讨Python并发编程中的GIL限制解决方案,结合内存管理机制优化,通过实际代码演示多进程绕过GIL、异步编程提升I/O效率等高级技术实践,帮助开发者

weixin_30847939的博客 382

C# WinForm 基于DirectShow.dll编写的程序,可边预览边保存视频,音频和图片

基于微软的DirectShow.dll的二次开发1.自动识别连接的摄像头跟麦克风且可以对其进行选择(默认选中第一个)2.可录制wmv和avi两种格式的视频并且都带有音频,avi可以录制的分辨率和帧数进行选择,wmv默认进行了淸晰度优化如不喜欢可去除代码中有相关提示3.可在预览点开之后进行拍照,也可边录制视频边拍照4.添加了视频和音频的压缩功能(酌情使用)这次二次开发发现C#对DirectShow的相关信息太少,这次做完也不敢藏私共享出来,还望大家指正

蓝易云 - 探索Python高级并发与网络编程技术。

如果使用单线程的方式,管家会先去喂狮子,再去喂大象,然后是河马,最后才是猩猩。而使用进程的方式,我们将整个动物园复制三份,每个复制品都有自己的一整套动物和管家,这样就无需再担心管家不能同时喂食所有动物的问题。高级并发和网络编程是Python族中的炙手可热的话题。开始时,可能有点云里雾里,但是一旦你跳入这个虚拟的深海并开始探索,你会发现你正在开启一扇全新的大门,而在这扇大门之后隐藏着另一个世界的无尽可能。探索这些技术,你将会发现:它们好比是Python世界的海洋,有穿越风暴的波涛,也有寂静深海的奇妙。

高性价比服务器就选:蓝易云 381

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

SIMATIC S7-1200, S7-1500 PID 控制[手册]

SIMATIC S7-1200, S7-1500 PID 控制[手册]

Python异步并发下载技术:B站视频下载工具的高级实现指南

# Python异步并发下载技术:B站视频下载工具的高级实现指南 B站视频下载工具是一个基于Python开发的开源项目,专门用于高效下载Bilibili视频内容,包括大会员专属的4K高清视频和充电专属内容。本文深入解析该工具的异步并发下载技术、模块化架构设计以及实战配置技巧,为技术爱好者和开发者提供专业的技术实现指南。🎯 ## 技术架构解析:策略模式与异步并发设计 ### 核心模块化架构

gitblog_00842的博客 82

TMS_WebGMaps_1.9.8.0_Full_Source

TMS_WebGMaps_1.9.8.0_Full_Source 全源码 delphi cbuilder

Pytest实践:掌握Python中的高级测试技术

使用pytest步入高级测试领域,预示着在你成为一名精通 Python 的开发测试人员的旅程中的又一个重要里程碑。从基本pytest功能到高级 pytest 功能的过渡就像换挡:它使你能够利用强大的测试策略在错综复杂的项目中游刃有余。测试不仅仅是开发过程中的一项任务,它还是一种理念,意在确保交付可靠、可维护和高质量的软件。随着项目复杂性的增加,先进测试技术的重要性也随之提升。当务之急是不仅要测试预期行为,还要预测和验证系统在意外或错误情况下的行为。

2301_76643199的博客 889

牛上天了,原来Python编程也可以实现高并发和高性能

学好Python的高阶编程,至少饭碗不会丢!

一个专注于嵌入式IoT领域的架构师,深耕IoT领域多年,深度掌握IoT领域的相关技术栈,包括但不限于RTOS内核的实现及其移植、硬件驱动移植开发、网络通讯协议开发、编译构建原理及其实现、底层汇编及编译原理、编译优化及代码重构、嵌入式IoT系统的架构设计等。 7583

python程序员工资怎么样_一位老程序员说,有这份python3的开发指南,月薪能突破20K...

推荐视频:有程序员说,这份python3的入门开发指南,深度分析和讲解了从其他途径无法获取的Python3使用和开发技术。大家都知道,程序员这个职业,向来都是技术至上,你只要有不俗的技术能力,月薪上超过20K,甚至是更多,都完全是可能的。很多即使才学不久python的人,看这份指南学习python,也能找到一份不错的程序员工作。那么这份python3的开发指南,到底有什么特别的地方呢?1、这是由一...

weixin_39525355的博客 136

Pytest实践:掌握Python中的高级测试技术(全)

使用pytest步入高级测试领域,预示着在你成为一名精通 Python 的开发测试人员的旅程中的又一个重要里程碑。从基本pytest功能到高级 pytest 功能的过渡就像换挡:它使你能够利用强大的测试策略在错综复杂的项目中游刃有余。测试不仅仅是开发过程中的一项任务,它还是一种理念,意在确保交付可靠、可维护和高质量的软件。随着项目复杂性的增加,先进测试技术的重要性也随之提升。当务之急是不仅要测试预期行为,还要预测和验证系统在意外或错误情况下的行为。

okcross0的博客 1215
上一篇: python实现生成带Logo的二维码
下一篇: Django中如何使用django-celery完成异步任务 (1)
youbo_sun
博客等级 码龄12年 20粉丝 51原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值