Python进阶——多线程,网络编程,正则表达式,递归(阶段八)

一,多线程

1.1进程

进程(process)是计算机中的一个基本概念,指的是正在运行中的程序实例。每个进程都是计算机系统中的一个独立执行单元,包含了程序代码、数据以及运行时的状态信息,如程序计数器、寄存器、内存地址空间等。

在操作系统中,进程是由操作系统创建和管理的,操作系统为每个进程分配资源,并为它们提供运行环境。进程之间是相互独立的,每个进程都有自己的内存空间和系统资源,互不干扰。同时,进程之间也可以通过进程间通信(IPC)机制进行通信和协作。

操作系统中的进程可以被分为两类:前台进程和后台进程。前台进程是指用户正在操作的程序,通常具有交互式界面;后台进程是指在后台运行的程序,通常不需要用户交互,如打印服务、网络服务等。

进程是操作系统中的基本概念,是实现多任务和并发的重要手段。通过合理地管理和调度进程,可以提高计算机系统的效率和性能。
在这里插入图片描述

1.2线程

线程(thread)是进程中的一个执行单元,也称为轻量级进程(lightweight process)。与进程不同的是,多个线程可以在同一个进程内并发执行,共享进程的内存和系统资源,相比进程而言,线程更加轻量级,创建、销毁和切换的代价更小,能够更加高效地利用系统资源。

在操作系统中,线程是由操作系统调度执行的,每个线程都有自己的线程栈和执行上下文。多个线程可以在同一个进程内共享相同的内存空间和系统资源,因此线程之间的通信和协作比进程之间更加高效和方便。线程之间的通信通常采用共享内存和消息传递等方式。

线程是实现多任务和并发的重要手段,也是实现异步编程的基础。通过合理地管理和调度线程,能够提高程序的执行效率和响应能力。
在这里插入图片描述

1.3总结

(1) 进程是计算机中正在运行的程序的实例。一个进程可以包含多个线程。每个线程都是进程中的一个执行流程,它可以独立执行,但与同一进程中的其他线程共享资源,如内存空间、文件句柄等。一个进程可以拥有多个线程,这些线程可以并发地执行任务,从而提高程序的性能和效率。

(2)线程是进程中的一条执行路径,是CPU调度和执行的基本单位。每个线程都有自己的执行栈和程序计数器,但它们共享进程的地址空间和系统资源。由于多个线程共享进程的资源,所以线程之间的通信和同步比进程之间更加高效和快速。
(3)各个进程相当于不同的公司,线程则是公司中的众多员工,使用公司的公共办公器材(资源),实际上干活的人还是公司员工(线程)。各个不同进程之间互不干扰,及各公司的办公场地不同。
(4)多线程并行:一家公司多个员工同时上班,处理不同的事物。

1.4多线程编程

1.4.1threading模块

  1. python的多线程可以通过threading模块中的Tread类实现,每创建一个Thread对象就创建了一个线程。
import  threading
thread_obj1=threading.Thread()
"""
-group:暂无用处,未来功能的预留参数
-target:执行的目标任务名,,一般是方法名
-args:以元组的方式给执行任务传参
-kwargs:以字典方式给执行任务传参
-name:线程名,一般不用设置
"""
thread_obj.start()
  1. 单线程实例:
import time
def sing():
    while True:
        print("我在唱歌!")
        time.sleep(1)
def dance():
    while True:
        print("我在跳舞!")
        time.sleep()
if __name__ == '__main__':
    sing()
    dance()

在这里插入图片描述
由于是单线程,导致一次只能执行一个程序,跳舞的程序无法执行。
3. 多线程实现

import  threading
import time
def sing():
    while True:
        print("我在唱歌!")
        time.sleep(1)
def dance():
    while True:
        print("我在跳舞!")
        time.sleep(1)
#定义两个线程
thread_obj1 = threading.Thread(target=sing)
thread_obj2 = threading.Thread(target=dance)
if __name__ == '__main__':
    thread_obj1.start()
    thread_obj2.start()

在这里插入图片描述
4. 实例三,实现传参->args(元组),kwargs(字典 )

import  threading
import time
def sing(msg):
    while True:
        print(msg)
        time.sleep(1)

def dance(msg):
    while True:
        print(msg)
        time.sleep(1)
#定义两个线程

thread_obj1 = threading.Thread(target=sing,args=("唱歌中",))#以元组传参
thread_obj2 = threading.Thread(target=dance,kwargs={"msg":"跳舞中"})#以字典传参
if __name__ == '__main__':
    thread_obj1.start()
    thread_obj2.start()

注意:对于传入的元组参数,如果元组只有一个值,要加逗号,否则只是普通的数值,如threading.Thread(target=sing,args=("唱歌中",))
在这里插入图片描述

二,网络编程

2.1socket简介

  1. Socket是一种抽象层,用于在网络上进行通信。在网络编程中,Socket通常是指一组API,这些API允许开发人员创建、发送和接收网络数据。Socket通常用于实现TCP/IP协议族中的网络编程。
  2. 以下是一些常用的Socket函数:
    socket()函数:创建一个Socket,并返回其文件描述符。
    bind()函数:将Socket与一个本地地址关联起来。
    listen()函数:将Socket转换为监听Socket,等待连接请求。
    accept()函数:接受连接请求,创建一个新的Socket,并返回其文件描述符。
    connect()函数:尝试连接到远程Socket。
    send()函数:将数据发送到Socket。
    recv()函数:从Socket接收数据。
    close()函数:关闭Socket。

2.2服务端开发

import socket
#创建Socket对象
socket_server=socket.socket()
#绑定IP地址和端口,以便于客户端通过IP和端口号链接客户端
socket_server.bind(("localhost",8888))
#监听端口
socket_server.listen(1)#listen内的参数是整数,表示允许链接的个数
#accept()方法返回的是一个二元元祖(连接对象,客户端地址信息),分别返回给conn,address
conn1,address=socket_server.accept()
"""注意accept()方法是一个阻塞方法,如果没有客户端链接,将不会继续执行下面的程序"""
#测试是否已经连接
print(f"客户端已连接!地址信息{address}")


while True:#使用循环使得链接持续
    #01接收客户端发送的信息
    """"要使用服务端与客户端本次连接对象conn,而非socket_server对象"""
    data:str=conn1.recv(1024).decode("utf-8")#注解:data是str类型
    #recv是receive缩写:接收的意思,参数表示缓冲区大小,decode("utf-8")用来解码,将字节数组转换为 字符串对象
    print(f"客户端发来的消息是{data}")
    #02发送消息
    msg=input("向客户的发送的消息:")
    if msg=='exit':
        break
    conn1.send(msg.encode("utf-8"))#encode将字符串准换为 字节数组对象

#关闭链接
conn1.close()#关闭的是本次链接对象

socket_server.close()#关闭整个服务器


借助工具:netAssist.exe,模拟客户端
在这里插入图片描述
注意:socket对象绑定端口号时bind()只能传入一个参数,传入元组。
在这里插入图片描述

2.3客户端开发

import socket
#创建socket对象
soc_client=socket.socket()
#链接服务端
soc_client.connect(('localhost',6666))#传入的是元组
#直接用soc_client对象发消息
while True:
    #发消息
    msg=input("请输入发送信息,客户端:")
    soc_client.send(msg.encode('utf-8'))#转换为字节数组
    #接收消息
    recv_data=soc_client.recv(1024).decode('utf-8')#recv()是阻塞方法
    print(f"接收的信息:{recv_data}")

#关闭链接
soc_client.close()

在这里插入图片描述

2.4实例

服务端:

import socket

HOST = 'localhost'
PORT = 8888

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.bind((HOST, PORT))
    s.listen()
    print('服务器已启动...')
    conn, addr = s.accept()
    + conn:
        print('连接已建立:', addr)
        while True:
            data = conn.recv(1024)
            if not data:
                break
            conn.sendall(data)

在上面的代码中,我们首先定义了HOST和PORT,分别代表服务器的主机名和端口号。然后使用socket函数创建一个新的套接字,指定协议族为AF_INET,表示IPv4,协议类型为SOCK_STREAM,表示TCP协议。接下来,使用bind函数将套接字绑定到指定的地址和端口上,并使用listen函数监听连接。一旦有新的连接请求到达,使用accept函数接受连接,并返回一个新的套接字和客户端的地址。然后进入一个循环,接收客户端发送的数据,并将其原样返回。
客户端:

import socket

HOST = 'localhost'
PORT = 8888

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
    s.connect((HOST, PORT))
    s.sendall(b'Hello, world')
    data = s.recv(1024)

print('Received:', data.decode())

在客户端程序中,我们首先定义了HOST和PORT,分别代表服务器的主机名和端口号。然后使用socket函数创建一个新的套接字,指定协议族为AF_INET,表示IPv4,协议类型为SOCK_STREAM,表示TCP协议。接下来,使用connect函数连接服务器,并使用sendall函数发送数据。然后等待服务器返回数据,并使用recv函数接收数据。最后输出收到的数据。

2.5两者比较

  1. 客户端:发送与接收消息都需要用accept返回的连接对象conn1进行操作,而客户端直接用socket对象,因为服务端可以链接很多客户端,因此需要创建不同的连接对象conn1,conn2…,只能通过对于的谅解对象进行发送接收消息。

在这里插入图片描述

三,正则表达式

3.0概念

  1. 正则表达式(Regular Expression,简称Regex或RegExp)是一种用于匹配、查找和替换文本中字符串的工具。它是一种通用的表达式语言,可以用于多种编程语言和文本编辑器中。
  2. 正则表达式可以用来解决很多问题,例如:
    (1)验证输入的字符串是否符合某种模式,例如验证邮箱、手机号码等;
    (2)在文本中查找符合某种模式的字符串;
    (3)替换文本中符合某种模式的字符串;
  3. 正则表达式由一系列字符和特殊符号组成,每个符号都有特殊的含义。常见的正则表达式符号包括:
    ^:匹配输入字符串的开始位置;
    :匹配输入字符串的结束位置; . :匹配任意单个字符; ∗ :匹配前一个字符的 0 次或多次出现; + :匹配前一个字符的 1 次或多次出现; ? :匹配前一个字符的 0 次或 1 次出现; [ ] :匹配中括号内的任意一个字符; ( ) :捕获匹配的子字符串。例如,正则表达 式 [ a − z ] + [ 0 − 9 ] ∗ :匹配输入字符串的结束位置; .:匹配任意单个字符; *:匹配前一个字符的0次或多次出现; +:匹配前一个字符的1次或多次出现; ?:匹配前一个字符的0次或1次出现; []:匹配中括号内的任意一个字符; ():捕获匹配的子字符串。 例如,正则表达式^[a-z]+[0-9]* :匹配输入字符串的结束位置;.:匹配任意单个字符;:匹配前一个字符的0次或多次出现;+:匹配前一个字符的1次或多次出现;?:匹配前一个字符的0次或1次出现;[]:匹配中括号内的任意一个字符;():捕获匹配的子字符串。例如,正则表达[az]+[09]可以匹配任意以小写字母开头、后跟0个或多个数字的字符串。

3.1基本匹配

  1. python的正则表达式使用re模块,使用前需要导包,并基于re模块的三个基础方法进行正则匹配。分别是:match,search,findall
  2. re.match(匹配规则,被匹配的字符串):从被匹配的字符串的开头开始匹配,匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回None
import re
#定义一待匹配字符串
s1="python itheima python"
s2="python1 itheima python"
#01match方法
result=re.match('python',s1)
result2=re.match('1python',s1)
print(result)#span:表示在是=s1中的位置
print(result.span())
print(result.group())
print(result2)#span:表示在是=s1中的位置

在这里插入图片描述

  1. re.search(匹配规则,被匹配字符串):搜索整个字符串,从前向后,直到找到第一个才停止,不会继续搜索。
#02search
import re
#定义一待匹配字符串
s1="python itheima python"
s2="1python itheima python"
result=re.search('python',s2)
print(result)
print(result.span())
print(result.group())

在这里插入图片描述

  1. re.findall(匹配规则,被匹配字符串):搜索字符串,找出全部匹配项,返回结果用列表存储,如果未找到返回空列表。
#03findall
import re
#定义一待匹配字符串
s1="python itheima python"
s2="1python itheima python"
result=re.findall('python',s1)
result2=re.findall('python3',s1)
print(result)
print(result2)

在这里插入图片描述

  1. 总结
    (1)match:从头开始匹配,匹配第一个命中项
    (2)search:全局匹配,匹配第一个命中项
    (3)findall:全局匹配,匹配所有命中项

3.2元字符匹配

3.2.1简单匹配

如果只是匹配某字符串子串不用加(^¥),如果匹配的是整体需要加上:r='^[0-9a-zA-Z]{6,10}$' # ^表示从头开始匹配到尾部$
在这里插入图片描述

import re
s="itheima @@python2 !!123 #"

#01找出大数字
result1=re.findall(r'\d',s)#字符串前面加r标记,表示字符串中的转义字符无效,就是普通字符串的意思
print(result1)
#02找出特殊字符,@,#,!等字符
result2=re.findall(r'\W',s)
print(result2)
#03找出所有益英文,数字字符
result3=re.findall(r'[a-zA-Z]',s)#[]中可以只填写一个字符表示匹配的对象,也可以填写很多字符a-z,A-Z,或者0-9数字
print(result3)
result4=re.findall(r'[0-9]',s)
print(result4)

3.2.2数量,边界匹配

在这里插入图片描述
在这里插入图片描述

import re
# s="itheima @@python2 !!123 #"

# #01找出大数字
# result1=re.findall(r'\d',s)#字符串前面加r标记,表示字符串中的转义字符无效,就是普通字符串的意思
# print(result1)
# #02找出特殊字符,@,#,!等字符
# result2=re.findall(r'\W',s)
# print(result2)
# #03找出所有益英文,数字字符
# result3=re.findall(r'[a-zA-Z]',s)#[]中可以只填写一个字符表示匹配的对象,也可以填写很多字符a-z,A-Z,或者0-9数字
# print(result3)
# result4=re.findall(r'[0-9]',s)
# print(result4)

#001匹配账号只能由字母和数字组成,\w不适合,因为其中还有一个下划线,长度6到10位
#定义规则
r='^[0-9a-zA-Z]{6,10}$' # ^表示从头开始匹配到尾部$
s='1234'
print(re.findall(r,s))#结果为空,没匹配上,s太短了
s2='1234ac'
print(re.findall(r,s2))

#002匹配QQ号,纯数字,长度5-11位第一位不为0
r2='^[1-9][0-9]{4,10}$'#因为前面[1-9]已经占以为所以后面长度控制{4,10}不是{5,11}
s3='1234567'
print(re.findall(r,s3))
#003匹配邮箱,只允许qq,163,gmail这三种地址
#{内容}.{内容}.{内容}.{..}.{..}.{..}@{..}.{..}.{..}:abc.efg.dow
r=r'(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)' #最外层加上一个r()用来控制这一串数据是一个整体,防止输出时里面内容是分散开的
#(1)[\w-]表示数字,字母,横杠 (2)+表示前面的数据至少出现一次(3)\.表示.本身(4)@(qq|163|gmail)(\.[\w-]+)+控制@后面的部分
s5="2331351349@qq.con"
print(re.findall(r,s5))

在这里插入图片描述
findall会将传入数据中有括号的进行分组,所以需要在最外层加个括号,以便能够输出整体,或使用re.match(r,s)方法

四,递归

4.1os模块三个常用方法

#需求:通过递归找到一个指定文件夹内的全部文件
#写一个函数,列出文件夹内的全部内容,如果是文件就收集到list,如果是文件夹,就递归调用自己,直到碰到文件夹

import os

def test_os():
    """演示os模块三个基本方法"""
    print(os.listdir("E:\pythonProject\Test"))#列出路径下的内容
    print(os.path.isdir("E:\pythonProject\Test/1"))#判断是否是文件夹,是的话返回Ture
    print(os.path.isdir("E:\pythonProject\Test/a"))#判断是否是文件夹,是的话返回Ture
    print(os.path.exists("E:\pythonProject\Test/a"))#判断路径是否存在


if __name__ == '__main__':
    test_os()

在这里插入图片描述

4.2实例

#需求:通过递归找到一个指定文件夹内的全部文件
#写一个函数,列出文件夹内的全部内容,如果是文件就收集到list,如果是文件夹,就递归调用自己,直到碰到文件夹

import os

# def test_os():
#     """演示os模块三个基本方法"""
#     print(os.listdir("E:\pythonProject\Test"))#列出路径下的内容
#     print(os.path.isdir("E:\pythonProject\Test/1"))#判断是否是文件夹,是的话返回Ture
#     print(os.path.isdir("E:\pythonProject\Test/a"))#判断是否是文件夹,是的话返回Ture
#     print(os.path.exists("E:\pythonProject\Test/a"))#判断路径是否存在

def get_files_from_dir(path):
    """
    :param path: 被判断的文件夹
    :return: list文件列表,如果文件不存在或者为空,返回空list
    """
    file_list=[]
    if os.path.exists(path):#判断路径是否有效
        for f in os.listdir(path):
            #文件夹名或者文件名读出来给f,然后与原路径进行组合,以便是文件夹的话继续向下读取
            new_path=path+"/"+f
            #判断new_path是否是文件夹,是的话递归调用get_files_from_dir继续打开,不是的话加入列表
            if os.path.isdir(new_path):
                #进入到这里表明目录是文件夹
                file_list+= get_files_from_dir(new_path)    #递归函数有返回值
            else:
                file_list.append(new_path)

    else:
        print("传入的路径为空或者不存在!")
        return []
    return file_list



if __name__ == '__main__':
    # test_os()
    print(get_files_from_dir("E:\pythonProject\Test"))

在这里插入图片描述

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

泰勒今天想展开

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值