当前位置: 首页 > news >正文

致敬白衣天使,学习Python读取

名字:阿玥的小东东

学习:Python、c++

主页:阿玥的小东东

故事设定:现在学校要求对所有同学进行核酸采集,每位同学先在宿舍内等候防护人员(以下简称“大白”)叫号,叫到自己时去停车场排队等候大白对自己进行采集,采集完之后的样本由大白统一有序收集并储存。

名词解释:

  • 学生:所有的学生是一个大文件,每个学生是其中的一行数据
  • 宿舍:硬盘
  • 停车场:内存
  • 核酸采集:数据处理
  • 样本:处理后的数据
  • 大白:程序

学生数量特别少的情况

当学生数量特别少时,可以考虑将所有学生统一叫到停车场等候,再依次进行核酸采集。

方法一:简单情况

此时的程序可以模拟为:

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

import time

from typing import List

  

  

def pick_all_students(dorm: str) -> List[str]:

    with open(dorm, "rt", encoding="utf8") as fin:

        students = fin.readlines()

        return students

  

  

def pick_sample(student: str) -> str:

    time.sleep(0.01)

    sample = f"{student.strip()}'s sample"

    return sample

  

  

def process(dorm: str, sample_storeroom: str) -> None:

    with open(sample_storeroom, "wt", encoding="utf8") as fout:

        students = pick_all_students(dorm)

        for student in students:

            sample = pick_sample(student)

            fout.write(f"{sample}\n")

            fout.flush()

  

  

if __name__ == "__main__":

    process(

        "student_names.txt",

        "sample_storeroom.txt"

    )

注意,在第19行中,大白一次性把所有同学都叫到了停车场中。这种做法在学生比较少时做起来很快,但是如果学生特别多,停车场装不下怎么办?

停车场空间不够时怎么办?

方法二:边读边处理

一般来说,由于停车场空间有限,我们不会采用一次性把所有学生都叫到停车场中,而是会一个一个地处理,这样可以节约内存空间。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

import time

from typing import Iterator

  

  

def pick_one_student(dorm: str) -> Iterator[str]:

    with open(dorm, "rt", encoding="utf8") as fin:

        for student in fin:

            yield student

  

  

def pick_sample(student: str) -> str:

    time.sleep(0.01)

    sample = f"{student.strip()}'s sample"

    return sample

  

  

def process(dorm: str, sample_storeroom: str) -> None:

    with open(sample_storeroom, "wt", encoding="utf8") as fout:

        for student in pick_one_student(dorm):

            sample = pick_sample(student)

            fout.write(f"{sample}\n")

            fout.flush()

  

  

if __name__ == "__main__":

    process(

        "student_names.txt",

        "sample_storeroom.txt"

    )

这里pick_one_student函数中的返回值是用yield返回的,一次只会返回一名同学。

不过,这种做法虽然确保了停车场不会满员,但是这种做法在人数特别多的时候就不再适合了。虽然可以保证完成任务,但由于每次只能采集一个同学,程序的执行并不高。特别是当你的CPU有多个核时,会浪费机器性能,出现一核有难,其它围观的现象。

怎么加快执行效率?

大家可能也已经注意到了,刚刚我们的场景中,不论采用哪种方法,都只有一名大白在工作。那我们能不能加派人手,从而提高效率呢?

答案当然是可行的。我们现在先考虑增加两名大白,使得一名大白专注于叫号,安排学生进入停车场,另外一名大白专注于采集核酸,最后一名大白用于存储核酸样本。

方法三

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

import time

from multiprocessing import Queue, Process

from typing import Iterator

  

  

def pick_student(stu_queue: Queue, dorm: str) -> Iterator[str]:

    print("pick_student: started")

  

    picked_num = 0

    with open(dorm, "rt", encoding="utf8") as fin:

        for student in fin:

            stu_queue.put(student)

            picked_num += 1

            if picked_num % 500 == 0:

                print(f"pick_student: {picked_num}")

  

    # end signal

    stu_queue.put(None)

    print("pick_student: finished")

  

  

def pick_sample(student: str) -> str:

    time.sleep(0.01)

    sample = f"{student.strip()}'s sample"

    return sample

  

  

def process(stu_queue: Queue, store_queue: Queue) -> None:

    print("process: started")

  

    process_num = 0

    while True:

        student = stu_queue.get()

        if student is not None:

            sample = pick_sample(student)

            store_queue.put(sample)

            process_num += 1

            if process_num % 500 == 0:

                print(f"process: {process_num}")

        else:

            break

  

    # end signal

    store_queue.put(None)

    print("process: finished")

  

  

def store_sample(store_queue: Queue, sample_storeroom: str) -> None:

    print("store_sample: started")

  

    store_num = 0

    with open(sample_storeroom, "wt", encoding="utf8") as fout:

        while True:

            sample = store_queue.get()

            if sample is not None:

                fout.write(f"{sample}\n")

                fout.flush()

  

                store_num += 1

                if store_num % 500 == 0:

                    print(f"store_sample: {store_num}")

            else:

                break

  

    print("store_sample: finished")

  

  

if __name__ == "__main__":

    dorm = "student_names.txt"

    sample_storeroom = "sample_storeroom.txt"

  

    stu_queue = Queue()

    store_queue = Queue()

  

    store_p = Process(target=store_sample, args=(store_queue, sample_storeroom), daemon=True)

    store_p.start()

    process_p = Process(target=process, args=(stu_queue, store_queue), daemon=True)

    process_p.start()

    read_p = Process(target=pick_student, args=(stu_queue, dorm), daemon=True)

    read_p.start()

  

    store_p.join()

这份代码中,我们引入了多进程的思路,将每个大白看作一个进程,并使用了队列Queue作为进程间通信的媒介。stu_queue表示学生叫号进停车场的队列,store_queue表示已经采集过的待存储核酸样本的队列。

此外,为了控制进程的停止,我们在pick_student和 process函数的最后都向各自队列中添加了None作为结束标志符。

假设有1w名学生(student_names.txt文件有1w行),经过测试后发现上述方法的时间如下:

  • 方法一:1m40.716s
  • 方法二:1m40.717s
  • 方法三:1m41.097s

咦?不是做了分工吗?怎么速度还变慢了?经笔者观察,这是因为叫号的大白速度太快了(文件读取速度快)通常是TA已经齐活了,另外俩人还在吭哧吭哧干活呢,体现不出来分工的优势。如果这个时候我们对法二和法三的叫号做延时操作,每个学生叫号之后停滞10ms再叫下一位学生,则方法三的处理时间几乎不变,而方法二的时间则会延长至3m21.345s。

怎么加快处理速度?

上面提到,大白采核酸的时间较长,往往上一个人的核酸还没采完,下一个人就已经在后面等着了。我们能不能提高核酸采集这个动作(数据处理)的速度呢?其实一名大白执行一次核酸采集的时间我们几乎无法再缩短了,但是我们可以通过增加人手的方式,来达到这个目的。就像去银行办业务,如果开放的窗口越多,那么每个人等待的时间就会越短。这里我们也采取类似的策略,增加核酸采集的窗口。

1

2

3

4

5

6

7

8

9

10

11

12

13

14

15

16

17

18

19

20

21

22

23

24

25

26

27

28

29

30

31

32

33

34

35

36

37

38

39

40

41

42

43

44

45

46

47

48

49

50

51

52

53

54

55

56

57

58

59

60

61

62

63

64

65

66

67

68

69

70

71

72

73

74

75

76

77

78

79

80

81

82

83

84

85

86

87

88

89

90

91

92

import time

from multiprocessing import Queue, Process, cpu_count

from typing import Iterator

  

  

def pick_student(stu_queue: Queue, dorm: str, num_workers: int) -> Iterator[str]:

    print("pick_student: started")

  

    picked_num = 0

    with open(dorm, "rt", encoding="utf8") as fin:

        for student in fin:

            stu_queue.put(student)

            picked_num += 1

            if picked_num % 500 == 0:

                print(f"pick_student: {picked_num}")

  

    # end signal

    for _ in range(num_workers):

        stu_queue.put(None)

  

    print("pick_student: finished")

  

  

def pick_sample(student: str) -> str:

    time.sleep(0.01)

    sample = f"{student.strip()}'s sample"

    return sample

  

  

def process(stu_queue: Queue, store_queue: Queue) -> None:

    print("process: started")

  

    process_num = 0

    while True:

        student = stu_queue.get()

        if student is not None:

            sample = pick_sample(student)

            store_queue.put(sample)

            process_num += 1

            if process_num % 500 == 0:

                print(f"process: {process_num}")

        else:

            break

  

    print("process: finished")

  

  

def store_sample(store_queue: Queue, sample_storeroom: str) -> None:

    print("store_sample: started")

  

    store_num = 0

    with open(sample_storeroom, "wt", encoding="utf8") as fout:

        while True:

            sample = store_queue.get()

            if sample is not None:

                fout.write(f"{sample}\n")

                fout.flush()

  

                store_num += 1

                if store_num % 500 == 0:

                    print(f"store_sample: {store_num}")

            else:

                break

  

    print("store_sample: finished")

  

  

if __name__ == "__main__":

    dorm = "student_names.txt"

    sample_storeroom = "sample_storeroom.txt"

    num_process = max(1, cpu_count() - 1)

  

    maxsize = 10 * num_process

    stu_queue = Queue(maxsize=maxsize)

    store_queue = Queue(maxsize=maxsize)

  

    store_p = Process(target=store_sample, args=(store_queue, sample_storeroom), daemon=True)

    store_p.start()

    process_workers = []

    for _ in range(num_process):

        process_p = Process(target=process, args=(stu_queue, store_queue), daemon=True)

        process_p.start()

        process_workers.append(process_p)

    read_p = Process(target=pick_student, args=(stu_queue, dorm, num_process), daemon=True)

    read_p.start()

  

    for worker in process_workers:

        worker.join()

  

    # end signal

    store_queue.put(None)

    store_p.join()

总耗时 0m4.160s !我们来具体看看其中的细节部分:

首先我们将CPU核数 - 3作为采核酸的大白数量。这里减3是为其它工作进程保留了一些资源,你也可以根据自己的具体情况做调整

这次我们在 Queue中增加了 maxsize参数,这个参数是限制队列的最大长度,这个参数通常与你的实际内存情况有关。如果数据特别多时要考虑做些调整。这里我采用10倍的工作进程数目作为队列的长度

注意这里pick_student函数中要为每个后续的工作进程都添加一个结束标志,因此最后会有个for循环

我们把之前放在process函数中的结束标志提取出来,放在了最外侧,使得所有工作进程均结束之后再关闭最后的store_p进程

结语

总结来说,如果你的数据集特别小,用法一;通常情况下用法二;数据集特别大时用法四。

相关文章:

致敬白衣天使,学习Python读取

名字:阿玥的小东东 学习:Python、c 主页:阿玥的小东东 故事设定:现在学校要求对所有同学进行核酸采集,每位同学先在宿舍内等候防护人员(以下简称“大白”)叫号,叫到自己时去停车场排…...

JVM - 认识JVM规范

目录 重识JVM JVM规范作用及其核心 JVM 整体组成 理解ClassFile结构 ASM开发 重识JVM JVM概述JVM: Java Virtual Machine,也就是Java虚拟机所谓虚拟机是指: 通过软件模拟的具有完整硬件系统功能的、运行在一个完全隔离环境中的计算机系统…...

文献阅读笔记 # CodeBERT: A Pre-Trained Model for Programming and Natural Languages

《CodeBERT: A Pre-Trained Model for Programming and Natural Languages》EMNLP 2020 (CCF-B)作者主要是来自哈工大、中山大学的 MSRA 实习生和 MSRA、哈工大的研究员。资源:code | pdf相关资源:RoBERTa-base | CodeNN词汇: bimodal: 双模态…...

openHarmony的UI开发

自适应布局 拉伸能力 ​ Blank在容器主轴方向上,空白填充组件具有自动填充容器空余部分的能力。仅当父组件为Row/Column时生效,即是线性布局。这样便可以在两个固定宽度或高度的组件中间添加一个Blank(),将剩余空间占满,从而实现…...

【JavaSE】深入HashMap

文章目录1. HashMap概述2. 哈希冲突3. 树化与退化3.1 树化的意义3.2 树的退化4. 二次哈希5. put方法源码分析6. key的设计7. 并发问题参考 如何防止因哈希碰撞引起的DoS攻击_hashmap dos攻击_双子孤狼的博客-CSDN博客 为什么 HashMap 要用 h^(h >>&#…...

华为机试题:HJ62 查找输入整数二进制中1的个数(python)

文章目录博主精品专栏导航知识点详解1、input():获取控制台(任意形式)的输入。输出均为字符串类型。1.1、input() 与 list(input()) 的区别、及其相互转换方法2、print() :打印输出。1、整型int() :将指定进制&#xf…...

代码随想录训练营一刷总结|

分为几个大部分: 数组 最先接触的部分,虽然说感觉是最简单的,但是需要掌握好基础,特别是小心循环。这里面需要再仔细看的就是螺旋矩阵那一块,其他的在后续刷的时候能用一种方法一次a就行。 链表 需要注意链表的基础…...

CSS中的几种尺寸单位

一、尺寸单位 CSS 支持多种尺寸单位,包括: px:像素,固定大小单位em:相对于当前元素字体大小的单位rem:相对于根元素(HTML)字体大小的单位%:相对于父元素的百分比单位vh…...

运维必会:ansible剧本(piaybook)

playbooks 概述以及实例操作 Playbooks 组成部分: Inventory Modules Ad Hoc Commands Playbooks Tasks: 任务,即调用模块完成的某些操作 Variables: 变量 Templates: 模板 Handlers: 处理器,由某时间触发执行的操作 Roles: 角色 YAML 介绍…...

活动星投票午间修身自习室制作在线投票投票制作网页

“午间修身自习室”网络评选投票_免费小程序投票推广_小程序投票平台好处手机互联网给所有人都带来不同程度的便利,而微信已经成为国民的系统级别的应用。现在很多人都会在微信群或朋友圈里转发投票,对于运营及推广来说找一个合适的投票小程序能够提高工…...

C#泛型:高级静态语言的效率利器

文章目录引入类型约束子类泛型常用的泛型数据结构前文提要: 💎超快速成,零基础掌握C#开发中最重要的概念💎抽丝剥茧,C#面向对象快速上手💎Winform,最友好的桌面GUI框架💎懂了委托&a…...

澳大利亚访问学者申请流程总结

澳大利亚访问学者申请需要注意些什么?下面知识人网小编整理澳大利亚访问学者申请流程总结。1、取得wsk英语成绩,现在都是先买票再上车了。2、联系外导,申请意向接收函(email)。3、向留学基金委CSC提出申请。4、获批后,申请正式邀请…...

cookie和Session的作用和比较

目录 什么是cookie cookie的工作原理 什么是session Session的工作原理 为什么会有session和cookie cookie和session如何配合工作 cookie和Session作用 什么是会话 什么是cookie cookie是web服务器端向我们客户端发送的一块小文件,该文件是干嘛的呢&#xf…...

测试员都是背锅侠?测试人员避“锅”攻略,拿走不谢

最近发生了一起生产事故,究其根源,事故本身属于架构或者需求层面需要规避的问题,测试人员的责任其实是非常小的,但实际情况是:相关测试人员因此承担了很大的压力,成为质量问题的“背锅侠”。 实际上&#…...

C++: C++模板<template>

C template content😊前言😁模板💕1、泛型编程😍2、函数模板😒2.1:函数模板概念👌2.2:函数模板的格式😘2.3:函数模板原理😁2.4:函数模…...

chmod命令详解

用法:chmod [选项]… 模式[,模式]… 文件…  或:chmod [选项]… 八进制模式 文件…  或:chmod [选项]… --reference参考文件 文件… Change the mode of each FILE to MODE. With --reference, change the mode of each FILE to that of R…...

状态机设计中的关键技术

⭐本专栏针对FPGA进行入门学习,从数电中常见的逻辑代数讲起,结合Verilog HDL语言学习与仿真,主要对组合逻辑电路与时序逻辑电路进行分析与设计,对状态机FSM进行剖析与建模。 🔥文章和代码已归档至【Github仓库&#xf…...

单片机开发---ESP32S3移植NES模拟器(二)

书接上文 《单片机开发—ESP32-S3模块上手》 《单片机开发—ESP32S3移植lvgl触摸屏》 《单片机开发—ESP32S3移植NES模拟器(一)》 暖场视频,小时候称这个为—超级曲线射门!!!!!&am…...

微信小程序nodej‘s+vue警局便民服务管理系统

本文首先介绍了设计的背景与研究目的,其次介绍系统相关技术,重点叙述了系统功能分析以及详细设计,最后总结了系统的开发心得在Internet高速发展的今天,我们生活的各个领域都涉及到计算机的应用,其中包括“最多跑一次”微信小程序的网络应用,在外国小程序的使用已经是很普遍的方…...

第18章 MongoDB $type 操作符教程

MongoDB $type 操作符 描述 在本章节中,咱们将继续讨论MongoDB中条件操作符 $type。 $type操作符是基于BSON类型来检索集合中匹配的数据类型,并return 结果。 MongoDB 中可以使用的类型如下表所示: 类型数字备注Double1 String2 Object3…...

【MySQL主从复制】快速配置

本文配置环境Windows和Linux。 windows主 Linux 从 一、主库配置 首先保证Linux和防火墙开启3306端口或关闭防火墙。 登录Mysql管理员账户: GRANT REPLICATION slave,reload,super ON *.* TO root@从库ip地址 IDENtIFIED BY root; flush privileges; 本地的mysql可以被:…...

Typescript - interface 关键字(通俗易懂的详细教程)

前言 简单来说,Interface 就是一种描述对象或函数的东西。 您可以把 interface 理解为形状,真实开发情况下,一个对象需要有什么样的属性,函数需要什么参数或返回什么样的值,数组应该是什么样子的,一个类和继…...

【计组】内存和总线

课程链接:深入浅出计算机组成原理_组成原理_计算机基础-极客时间 一、虚拟内存和内存保护 日常使用的操作系统下,程序不能直接访问物理内存。内存需要被分成固定大小的页(Page),再通过虚拟内存地址(Virtu…...

CUDA中的数学方法

CUDA中的数学方法 文章目录CUDA中的数学方法1. Standard FunctionsSingle-Precision Floating-Point FunctionsDouble-Precision Floating-Point Functions2. Intrinsic FunctionsSingle-Precision Floating-Point FunctionsDouble-Precision Floating-Point Functions参考手册…...

Elasticsearch基本概念和索引原理

一、Elasticsearch是什么? Elasticsearch是一个基于文档的NoSQL数据库,是一个分布式、RESTful风格的搜索和数据分析引擎,同时也是Elastic Stack的核心,集中存储数据。Elasticsearch、Logstash、Kibana经常被用作日志分析系统&…...

《NFL橄榄球》:堪萨斯城酋长·橄榄1号位

堪萨斯城酋长队(Kansas City Chiefs)是位于密苏里州堪萨斯城的职业美式橄榄球队;目前在全国橄榄球联盟隶属于美国橄榄球联合会(AFC)西区;其夏季训练营在威斯康星大学河瀑校区举行。 酋长队的前身是达拉斯得州佬队,这支…...

python+django在线教学网上授课系统vue

随着科技的进步,互联网已经开始慢慢渗透到我们的生活和学习中,并且在各个领域占据着越来越重要的部分,很多传统的行业都将面临着巨大的挑战,包括学习也不例外。现在学习竞争越来越激烈,人才的需求量越来越大&#xff0…...

二叉搜索树之AVL树

AVL树的概念二叉搜索树虽可以缩短查找的效率,但如果数据有序或接近有序二叉搜索树将退化为单支树,查找元素相当于在顺序表中搜索元素,效率低下。因此,两位俄罗斯的数学家G.M.Adelson-Velskii和E.M.Landis在1962年 发明了一种解决上…...

全栈自动化测试技术笔记(二):准备工作的切入点

自动化测试技术笔记(二):准备工作的切入点 上篇整理的技术笔记,聊了自动化测试的前期调研工作如何开展,最后一部分也提到了工作的优先级区分。 这篇文章,接上篇文章的内容,来聊聊自动化测试前期的准备工作&#xff0…...

57 长短期记忆网络(LSTM)【动手学深度学习v2】

57 长短期记忆网络(LSTM)【动手学深度学习v2】 深度学习学习笔记 学习视频:https://www.bilibili.com/video/BV1JU4y1H7PC/?spm_id_fromautoNext&vd_source75dce036dc8244310435eaf03de4e330 长短期记忆网络(LSTM&#xff09…...

成都哪里有做网站的/bt搜索引擎下载

基于多尺度窗口的DEM局部填洼方法徐静波1,许捍卫1,于艳超2【摘要】为了去除DEM中的伪洼地,使水系提取结果更加精确,在M&V算法的基础上提出了一种改进的填洼方法。用局部处理的思想将填洼步骤简化,减小对DEM的计算范…...

wordpress电子邮件要用什么/适合小学生的新闻事件

C#零基础入门 结构体和枚举 -- 结构体变量的使用 -- 学生数据存储 前言一,结构体变量二,结构体数组2.1 结构体类型数组定义2.2 结构体类型数组使用三,实例练习 -- 学生成绩排序 -- 排序拓展3.1 题目描述3.2 问题分析3.3 参考代码前言 本文属于C#零基础入门之百识百例系列文章…...

织梦做的网站打包在dw修改/佛山市seo推广联系方式

vue 3.x 马上就要问世了,显然尤大大是不想让我们好好活了,但是转念一想,比你优秀的人都还在努力,那我们努力还有什么用,开个玩笑而已,本人对于 vue 的接触时间不长,对其也没有深入地去研究源码&…...

洛阳平台公司/seo成都培训

可以使用 IN 子句代替许多 OR 条件。要想理解 IN 子句,还以表 employee_tbl 为例,它的所有记录如下所示:mysql> SELECT * FROM employee_tbl;--------------------------------------------| id | name | work_date | daily_typing_pages …...

简单ppt模板下载免费完整版/appstore关键词优化

在互联网上拥有数十亿个网站来生存是非常复杂的,并且涉及棘手的方法。在互联网上拥有数十亿个网站来生存是非常复杂的,并且涉及棘手的方法。要在百度上排名更高,必须进行搜索引擎优化,但是要使电子商务在网络上清晰可见&#xff0…...

网络营销是啥意思/seo案例模板

仅作为记录,大佬请跳过。 是行间距的问题 解决 段落——行间距的固定值改为单倍行距。即可 参考 传送门...