Python学习打卡:day18

day18

笔记来源于:黑马程序员python教程,8天python从入门到精通,学python看这套就够了

7、Socket服务端开发

Socket基础概念

socket (简称 套接字) 是进程之间通信一个工具,好比现实生活中的插座,所有的家用电器要想工作都是基于插座进行,进程之间想要进行网络通信需要socket

Socket负责进程之间的网络数据传输,好比数据的搬运工。

在这里插入图片描述

客户端和服务端

2个进程之间通过 Socket 进行相互通讯,就必须有服务端和客户端。

Socket服务端:等待其它进程的连接、可接受发来的消息、可以回复消息;

Socket客户端:主动连接服务端、可以发送消息、可以接收回复。

Socket 服务端编程

主要分为如下几个步骤:

  1. 创建 socket 对象

    import socket
    # 创建 Socket 对象
    socket_server = socket.socket()
    
  2. 绑定 socket_server 到指定 IP 和地址

    socket_server.bind(host, port)
    
    # 示例
    socket_server.bind(("localhost", 8888 ))
    
  3. 服务端开始监听端口

    # 监听端口
    # backlog 为 int 整数,表示允许的连接数量,超出的会等待,可以不填,不填会自动设置一个合理值
    socket_server.listen(backlog)
    
    # 示例
    socket_server.listen(1)
    # listen 方法接受一个整数,表示接受的连接数量
    
  4. 接收客户端连接,获得连接对象

    # 等待客户端链接
    # result: tuple = socket_server.accept()
    # conn = result[0]        # 客户端和服务端的链接对象
    # address = result[1]     # 客户端的地址信息
    # 简便写法
    conn, address = socket_server.accept()
    # accept 方法返回的是二元元组(链接对象, 客户端地址信息)
    # 可以通过 变量1, 变量2 = socket_server.accept() 的形式,直接接受二元元组内的两个元素
    # accept() 方法是阻塞的方法,等待客户端的链接,如果没有连接,就卡在这一行不再向下执行了
    
    print(f"接收到了客户端的链接,客户端信息是:{address}")
    
  5. 客户端连接后,通过recv方法,接收客户端发送的消息

    # 接收客户端信息, 要使用客户端和服务端本次的链接对象,而非 socket_server 对象
    data = conn.recv(1024).decode("UTF-8")
    # recv 接收的参数是缓冲区大小:一般给 1024 即可
    # recv 方法的返回值是一个字节数组,也就是 bytes 对象,不是字符串,可以通过decode方法通过 UTF-8 编码,将字符数组转换为字符串对象
    print(f"客户端发来的消息是: {data}")
    
  6. 通过conn(客户端当次连接对象),调用send方法可以回复消息

    # 发送回复消息
    msg = input("请输入你和客户端要回复的消息:").encode("UTF-8")      # encode可以将字符串编码为字节数组对象
    conn.send(msg)
    
  7. conn(客户端当次连接对象)和socket_server对象调用close方法,关闭连接

    # 关闭链接
    conn.close()
    socket_server.close()
    

示例代码:

"""
演示 Socket 服务端开发
"""

import socket

# 创建 Socket 对象
socket_server = socket.socket()

# 绑定ip和端口
# socket_server.bind(host, port)
socket_server.bind(("localhost", 8888))

# 监听端口
# socket_server.listen(backlog)
socket_server.listen(1)
# listen 方法接受一个整数,表示接受的连接数量

# 等待客户端链接
# result: tuple = socket_server.accept()
# conn = result[0]        # 客户端和服务端的链接对象
# address = result[1]     # 客户端的地址信息
# 简便写法
conn, address = socket_server.accept()
# accept 方法返回的是二元元组(链接对象, 客户端地址信息)
# 可以通过 变量1, 变量2 = socket_server.accept() 的形式,直接接受二元元组内的两个元素
# accept() 方法是阻塞的方法,等待客户端的链接,如果没有连接,就卡在这一行不再向下执行了

print(f"接收到了客户端的链接,客户端信息是:{address}")

while True:
    # 接收客户端信息, 要使用客户端和服务端本次的链接对象,而非 socket_server 对象
    data = conn.recv(1024).decode("UTF-8")
    # recv 接收的参数是缓冲区大小:一般给 1024 即可
    # recv 方法的返回值是一个字节数组,也就是 bytes 对象,不是字符串,可以通过decode方法通过 UTF-8 编码,将字符数组转换为字符串对象
    print(f"客户端发来的消息是: {data}")
    # 发送回复消息
    msg = input("请输入你和客户端要回复的消息:")
    if msg == 'exit':
        break
    conn.send(msg.encode("UTF-8"))      # encode可以将字符串编码为字节数组对象

# 关闭链接
conn.close()
socket_server.close()

网络调试助手

下载网络调试助手作为客户端

示例:

在这里插入图片描述

8、Socket客户端编程

主要分为如下几个步骤:

  1. 创建 socket 对象

    import socket
    
    # 创建 Socket 对象
    socket_client = socket.socket()
    
  2. 连接到服务端

    # 连接到服务器
    socket_client.connect(("localhost", 8888))
    
  3. 发送消息

    while True:
        # 发送信息
        msg = input("请输入要给服务端发送的消息:")
        if msg == 'exit':
            break
        socket_client.send("你好呀".encode("UTF-8"))
    
  4. 接收返回消息

    while True:
        # 发送信息
        msg = input("请输入要给服务端发送的消息:")
        if msg == 'exit':
            break
        socket_client.send("你好呀".encode("UTF-8"))
    
        # 接收返回消息
        recv_data = socket_client.recv(1024)        # 1024是缓冲区的大小,一般1024即可.同样recv方法是阻塞的
        print(f"服务端回复的消息是: {recv_data.decode('UTF-8')}")
    
  5. 关闭连接

    # 关闭链接
    socket_client.close()
    

示例代码:

"""
演示 Socket 客户端开发
"""

import socket

# 创建 Socket 对象
socket_client = socket.socket()

# 连接到服务器
socket_client.connect(("localhost", 8888))

while True:
    # 发送信息
    msg = input("请输入要给服务端发送的消息:")
    if msg == 'exit':
        break
    socket_client.send("你好呀".encode("UTF-8"))

    # 接收返回消息
    recv_data = socket_client.recv(1024)        # 1024是缓冲区的大小,一般1024即可.同样recv方法是阻塞的
    print(f"服务端回复的消息是: {recv_data.decode('UTF-8')}")
# 关闭链接
socket_client.close()

9、正则表达式—— 基础方法

正则表达式,又称规则表达式(Regular Expression),是使用单个字符串来描述、匹配某个句法规则的字符串,常被用来检索、替换那些符合某个模式(规则)的文本

简单来说,正则表达式就是使用:字符串定义规则,并通过规则去验证字符串是否匹配。

比如,验证一个字符串是否是符合条件的电子邮箱地址,只需要配置好正则规则,即可匹配任意邮箱。

比如通过正则规则: (^[\w-]+(\.[\w-]+)*@[\w-]+(\.[\w-]+)+$) 即可匹配一个字符串是否是标准邮箱格式。

但如果不使用正则,使用if else来对字符串做判断就非常困难了。

正则的三个基础方法

Python正则表达式,使用re模块,并基于re模块中三个基础方法来做正则匹配。

分别是:match、search、findall 三个基础方法

  • re.match(匹配规则, 被匹配字符串)

从被匹配字符串开头进行匹配, 匹配成功返回匹配对象(包含匹配的信息),匹配不成功返回空。

# match
s= "python itheima python python"
# match 从头匹配
result = re.match("python", s)
print(result)
print(result.span())
print(result.group())

# 结果
<re.Match object; span=(0, 6), match='python'>
(0, 6)
python

s= "1python itheima python python"
# match 从头不匹配
result = re.match("python", s)
print(result)

# 结果
None
  • search(匹配规则, 被匹配字符串)

    搜索整个字符串,找出匹配的。从前向后,找到第一个后,就停止,不会继续向后,整个字符串都找不到,返回 None

    # search 搜索匹配
    s= "1python itheima python python"
    result = re.search("python", s)
    print(result)
    
    # 结果
    <re.Match object; span=(1, 7), match='python'>
    
    
    # search 搜索不匹配
    s= "1python itheima python python"
    result = re.search("python2", s)
    print(result)
    
    # 结果
    None
    
  • findall(匹配规则, 被匹配字符串)

    匹配整个字符串,找出全部匹配项

    找不到返回空 list: []

    # findall 搜索全部匹配
    s= "1python itheima python python"
    result = re.findall("python", s)
    print(result)
    
    # 结果
    ['python', 'python', 'python']
    
    
    # findall 搜索全部匹配
    s= "1python itheima python python"
    result = re.findall("python2", s)
    print(result)
    
    # 结果
    []
    

10、正则表达式—— 元字符匹配

正则最强大的功能在于元字符匹配规则。

单字符匹配

在这里插入图片描述

示例:

字符串 s = "itheima1 @@python2 !!666 ##itcast3"

  • 找出全部数字: re.findall(r‘\d’, s)

字符串的r标记,表示当前字符串是原始字符串,即内部的转义字符无效而是普通字符

  • 找出特殊字符:re.findall(r‘\W’, s)

  • 找出全部英文字母:re.findall(r’[a-zA-Z]’, s)

[]内可以写:[a-zA-Z0-9] 这三种范围组合或指定单个字符如[aceDFG135]

示例代码:

"""
演示 Python 正则表达式使用元字符进行匹配
"""
import re

# 单字符匹配
s = "itheima1 @@python2 !!666 ## itccast3"

# 找出所有数字
result = re.findall(r'\d', s)       # 字符串前面带上 r 的标记, 表示字符串转义字符无效,就是普通字符的意思
print(result)
# 结果
['1', '2', '6', '6', '6', '3']


# 找出所有的非单词字符
result = re.findall(r'\W', s)
print(result)
# 结果
[' ', '@', '@', ' ', '!', '!', ' ', '#', '#', ' ']


# 找出所有的单词字符 和 数字
result = re.findall(r'[a-zA-Z]', s)
print(result)
result = re.findall(r'[0-9]', s)
print(result)
# 结果
['i', 't', 'h', 'e', 'i', 'm', 'a', 'p', 'y', 't', 'h', 'o', 'n', 'i', 't', 'c', 'c', 'a', 's', 't']
['1', '2', '6', '6', '6', '3']

数量匹配

在这里插入图片描述

边界匹配

在这里插入图片描述

分组匹配

在这里插入图片描述

案例

  1. 匹配账号,只能由字母和数字组成,长度限制6到10位

    规则为: ^[0-9a-zA-Z]{6, 10}$

    示例代码:

    # 匹配账号, 只能由字母和数字组成,长度限制 6 到 10 位
    r = '^[a-zA-Z0-9]{6,10}$'       # 注意正则表达式没有多余的空格
    s = '123456'
    print(re.findall(r, s))
    
    # 结果
    ['123456']
    
  2. 匹配QQ号,要求纯数字,长度5-11,第一位不为0

    规则为:^[1-9][0-9]{4, 10}&

    [1-9]匹配第一位,[0-9]匹配后面4到10位

    示例代码:

    # 匹配 QQ 号:要求纯数字,长度 5-11,第一位不为 0
    r = '^[1-9][0-9]{4,10}$'
    s = '012345678'
    print(re.findall(r, s))
    
    # 结果
    []
    
  3. 匹配邮箱地址,只允许qq、163、gmail这三种邮箱地址

    规则为:^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+&

    • [\w-]+ 表示出现 a-z A-Z 0-9 _- 字符最少一个,最多不限

    • (\.[\w-]+)*,表示出现组合 .a-z A-Z 0-9 _ - 的组合最少0次,最多不限,用于匹配:abc.ced.efg@123.com中的ced.efg这部分

    • @ 表示匹配 @ 符号

    • (qq|163|gmail) 表示只匹配这3个邮箱提供商

    • (\.[\w-]+)+ 表示 a-z A-Z 0-9 _ - 的组合最少1次,最多不限

      用于匹配 abc.ced.efg@123.com.cn 中的 .com.cn 这种

      最后使用 + 表示最少一次,即比如:.com

      多了可以是:.com.cn.eu 这样

    示例代码:

    # 匹配邮箱地址,只允许 qq、163、gmail这三种邮箱地址
    # {内容}.{内容}.{内容}.{内容}.{内容}.{内容}.{内容}@{内容}.{内容}.{内容}
    r = '(^[\w-]+(\.[\w-]+)*@(qq|163|gmail)(\.[\w-]+)+$)'
    s = 'a.b.c.d.e@163.com.a.z.c.d.e'
    print(re.findall(r, s))
    print(re.match(r, s))
    
    # 结果
    [('a.b.c.d.e@163.com.a.z.c.d.e', '.e', '163', '.e')]
    <re.Match object; span=(0, 27), match='a.b.c.d.e@163.com.a.z.c.d.e'>
    

11、递归

递归概念

递归在编程中是一种非常重要的算法

递归: 即方法(函数)自己调用自己的一种特殊编程写法

如:
在这里插入图片描述

函数调用自己,即称之为递归调用。

递归找文件

最典型的递归场景为找出一个文件夹中全部的文件。

在这里插入图片描述

在这里插入图片描述

os 模块的 3个方法

有如下文件结构:

$ tree -L 3
.
├── 1.txt
├── 2.txt
├── 3.txt
├── a
│   ├── a1.txt
│   ├── a2.txt
│   └── a3.txt
└── b
    ├── b1.txt
    ├── b2.txt
    └── b3.txt

2 directories, 9 files

示例代码:

import os

def Test_os():
    """演示 os 模块的 3个基础方法"""
    # 列出文件下的内容  (给出一个文件夹内的所有文件和文件夹)
    print(os.listdir("/home/yin-roc/hf_all"))
    # 判断指定路径是否是文件夹  (判断所给的路径是否是一个文件夹,是则返回 True,否则返回 False)
    print(os.path.isdir("/home/yin-roc/hf_all"))
    # 判断指定路径是否存在    (判断一个路径是否存在,是则返回 True,否则返回 False)
    print(os.path.exists("/home/yin-roc/hf_all"))
    
if __name__ == '__main__':
    Test_os()
    
# 结果
['a', '1.txt', '3.txt', 'b', '2.txt']
True
True

案例

有如下文件结构:

$ tree -L 3
.
├── 1.txt
├── 2.txt
├── 3.txt
├── a
│   ├── a1.txt
│   ├── a2.txt
│   └── a3.txt
└── b
    ├── b1.txt
    ├── b2.txt
    └── b3.txt

2 directories, 9 files

示例代码:

"""
演示 Python 的操作
需求:通过递归,找出一个指定文件夹内的全部文件

思考:写一个函数,列出文件夹的全部内容,如果是文件就收集到 list
如果是文件夹,就递归调用自己,再次判断
"""
import os

def get_files_recursion_from_dir(path):
    """
    从指定的文件夹中使用递归模式,获取全部的文件列表
    :param path: 被判断的文件夹
    :return: 包含全部的文件,如果目录不存在或者无文件就返回一个list
    """
    print(f"当前判断的文件夹是: {path}")
    file_list = []
    if os.path.exists(path):
        for f in os.listdir(path):
            new_path = path + "/" + f
            if os.path.isdir(new_path):
                # 进入到这里,表明这个目录是文件夹不是文件
                file_list += get_files_recursion_from_dir(new_path)
            else:
                file_list.append(new_path)
    else:
        print(f"指定的目录{path}, 不存在")
        return []

    return file_list


if __name__ == '__main__':
    print(get_files_recursion_from_dir("/home/yin-roc/test"))
    
# 结果
当前判断的文件夹是: /home/yin-roc/test
当前判断的文件夹是: /home/yin-roc/test/a
当前判断的文件夹是: /home/yin-roc/test/b
['/home/yin-roc/test/a/a3.txt', '/home/yin-roc/test/a/a2.txt', '/home/yin-roc/test/a/a1.txt', '/home/yin-roc/test/1.txt', '/home/yin-roc/test/3.txt', '/home/yin-roc/test/b/b3.txt', '/home/yin-roc/test/b/b1.txt', '/home/yin-roc/test/b/b2.txt', '/home/yin-roc/test/2.txt']
  • 23
    点赞
  • 10
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值