Python高级和Linux高级编程
1.Linux命令
这部分知识需要多敲命令。记住常用的命令,遇到不会的百度查找即可。没有不要死记硬背。
1.1Linux基础命令
1.1.1操作系统
操作系统是一个控制硬件和支持软件运行的计算机程序,只有安装了操作系统计算机才能进行正常工作。
1.1.2 虚拟机软件
我们可以借助虚拟机来完成
1.1.3 Ubuntu操作系统
- Ubuntu操作系统属于Linux操作系统中的一种
- Ubuntu操作系统窗口菜单条会隐藏,鼠标移动上去会显示,而Windows操作系统的窗口菜单条不会隐藏。
- Windows操作系统有可能会有多个盘符(C、D、E、F)
- Ubuntu操作系统没有多个盘符,只有一个根目录(/)
- Ubuntu操作系统比Windows操作系统运行更加稳定。
1.1.4 Linux内核及发行版
- Linux内核是Linux操作系统管理硬件设备的核心程序
- 常用的Linux操作系统都是基于Linux内核开发出来的
1.1.5 查看目录命令
- ls和tree是我们查看目录信息最常用的命令
- ls只能查看一层目录信息
- tree可以查看多层目录信息。
1.1.6 切换目录命令
- ls和tree是我们查看目录信息最常用的命令
- ls只能查看一层目录信息
- tree可以查看多层目录信息。
1.1.7 绝对路径和相对路径
绝对路径和相对路径是路径的两种表现形式,应遵循最短路径原则(使用最短的路径操作某个文件或者目录)。
- 如果切换的目录离当前目录近可以使用相对路径
- 如果切换的目录离根目录近可以使用绝对路径
- 如果切换的目录离根目录和当前目录都一样那么使用绝对路径,因为这样路径很清楚和明确,方便阅读。
1.1.8 创建、删除文件及目录命令
- ouch 表示创建文件
- mkdir 表示创建目录
- rm 表示删除文件或者目录,如果删除目录需要使用 -r 选项,-r 表示递归删除目录及其内容
- rmdir 表示删除空目录
1.1.9复制、移动文件及目录命令
- cp:拷贝目录需要加上 –r 选项
- mv:移动目录不需要加选项
- mv:命令还可以重命名文件和目录
1.1.10终端命令格式的组成
- 终端命令完整格式: 命令名 选项(可选) 参数(可选)
- 选项:用于调整命令的功能,比如:-r选项调整cp命令的功能。
- 选项可以分为短选项和长选项
- 短选项的格式: '-'后面接单个字母, 比如:-r
- 长选项的格式: '–'后面接单词, 比如:–help
- 参数:命令的操作对象,一般是文件名或者目录名。
- 对于命令,它的选项和参数一般情况下没有顺序要求,但是scp命令是必须先选项然后在跟上参数
1.1.11查看命令帮助
–help和man是查看命令帮助的两种方式,主要是查看命令所对应的选项信息
1.1.12 ls命令选项
ls不同选项会呈现不同的显示方式,其中-l和-a选项最常用
1.1.13 mkdir和rm命令选项
- 创建嵌套文件夹使用 “mkdir –p” 嵌套目录
- 删除空目录使用 “rmdir 目录名” 或者 “rm –d 目录名”
- 删除非空目录使用 “rm –r 目录名”
1.1.14 cp和mv命令选项
- 拷贝文件防止覆盖使用 “cp –i” 操作
- 拷贝文件夹使用 “cp –r” 操作,拷贝文件夹并且文件权限不丢失使用 “cp –a” 操作。
- 移动文件防止覆盖使用 “mv –i” 操作
- 移动文件夹直接使用 “mv” 即可,“mv” 还可以给文件和文件夹重命名。
1.2Linux高级命令
1.2.1 重定向命令
- 终端内容保存到文件使用重定向有两种方式: > 和 >>
- > 表示每次只写入最新的数据,原有数据不保留。
- >> 表示每次在原有数据的基础上进行追加,原有数据会保留
1.2.2 查看文件内容命令
- 查看小文件使用 cat 命令
- 分屏查看大型文件使用 more 命令,
- 查看终端显示内容并分屏展示,使用 管道(|) 结合 more 命令
1.2.3 链接命令
- 硬链接的作用是可以给重要文件创建硬链接,能够防止文件数据被误删。
- 删除源文件,软链接失效,但是硬链接依然可以使用。
- 创建硬链接命令格式: ln 源文件路径 硬链接
1.2.4 文本搜索命令
- grep 命令是完成文本搜索操作的
- 文本搜索的命令格式: grep 选项 文本搜索内容
1.2.5 查找文件命令
- find命令是完成查找文件操作的
- 查找文件的命令格式: find 指定查找目录 -name “文件名”
1.2.6 压缩和解压缩命令
- .gz和.bz2的压缩文件使用tar命令来完成压缩和解压缩
- .zip的压缩文件使用zip和unzip命令来完成压缩和解压缩
1.2.7 文件权限命令
- 利用 chmod 命令可以控制文件的操作权限。
- 字母法格式: chmod 不同角色设置的权限 文件
- 数字法格式: chmod 不同角色的权限值 文件名
1.2.8 获取管理员权限的相关命令
- sudo 是临时获取管理员权限
- sudo -s 是切换到管理员用户,一直使用管理员权限,需要谨慎操作。
- exit 是退出当前用户
- passwd 默认修改当前用户密码
1.2.9 用户相关操作
- 创建用户命令格式: sudo useradd -m 用户名, 默认会创建一个同名的用户组。
- 查看用户信息使用 id 命令或者 /etc/passwd文件
- 查看用户组信息使用 /etc/group文件
- 给用户设置密码使用 sudo passwd 用户名
- 切换用户使用 su - 用户名
- 设置附加组使用 sudo usermod -G 组名 用户名
- 删除用户使用 sudo userdel -r 用户名,默认会删除同名的用户组。
1.2.10用户组相关操作
- 创建用户组使用: sudo groupadd 用户组名
- 创建用户并指定用户组使用: sudo useradd -m -g 用户组 用户名
- 修改用户组使用: sudo usermod -g 用户组 用户名
- 删除用户组使用: sudo groupdel 用户组名
1.2.11 远程登录、远程拷贝命令
- ssh命令是远程登录主机电脑,相当于直接操作的是远程电脑。
- scp命令是可以完成远程拷贝操作,注意:拷贝文件夹需要加-r选项。
- 大量的文件上传和下载可以通过可视化工具FileZilla来完成。
1.2.12 编辑器vim
vim 是一款功能强大的命令文本编辑器,可以对远程服务器的代码直接进行修改,这样操作起来更加快速和方便。
1.2.13 软件安装和卸载
软件安装
- Ubuntu 操作系统安装软件有两种方式:
- sudo dpkg -i 安装包 命令
- sudo apt-get install 安装包 命令卸载
- 使用 apt-get 命令也就是在线安装需要更改镜像源,提高下载和安装速度
软件卸载
Ubuntu 操作系统卸载软件有两种方式:
- dpkg -r 安装包 命令
- apt-get remove 安装包 命令卸载
2.多任务编程
2.1多任务介绍
- 使用多任务就能充分利用CPU资源,提高程序的执行效率,让你的程序具备处理多个任务的能力。
- 多任务执行方式有两种方式:并发和并行,这里并行才是多个任务真正意义一起执行。
2.2进程
- 进程是操作系统进行资源分配的基本单位。
- 进程是Python程序中实现多任务的一种方式
2.3 多进程的使用
- 导入进程包
- import multiprocessing
- 创建子进程并指定执行的任务
- sub_process = multiprocessing.Process (target=任务名)
- 启动进程执行任务
- sub_process.start()
2.4 获取进程编号
- 获取当前进程编号
- os.getpid()
- 获取当前父进程编号
- os.getppid()
- 获取进程编号可以查看父子进程的关系
2.5获取进程执行带有参数的任务
进程执行任务并传参有两种方式:
- 元组方式传参(args): 元组方式传参一定要和参数的顺序保持一致。
- 字典方式传参(kwargs): 字典方式传参字典中的key一定要和参数名保持一致。
2.6进程的注意点
- 为了保证子进程能够正常的运行,主进程会等所有的子进程执行完成以后再销毁,设置守护主进程的目的是主进程退出子进程销毁,不让主进程再等待子进程去执行。
- 设置守护主进程方式: 子进程对象.daemon = True
- 销毁子进程方式: 子进程对象.terminate()
2.7 线程
线程是Python程序中实现多任务的另外一种方式,线程的执行需要cpu调度来完成。
2.8 多线程的使用
- 导入线程模块
- import threading
- 创建子线程并指定执行的任务
- sub_thread = threading.Thread(target=任务名)
- 启动线程执行任务
- sub_thread.start()
2.9 线程执行带有参数的任务
线程执行任务并传参有两种方式:
- 元组方式传参(args) :元组方式传参一定要和参数的顺序保持一致。
- 字典方式传参(kwargs):字典方式传参字典中的key一定要和参数名保持一致。
2.10 线程的注意点
- 线程执行执行是无序的
- 主线程默认会等待所有子线程执行结束再结束,设置守护主线程的目的是主线程退出子线程销毁。
- 线程之间共享全局变量,好处是可以对全局变量的数据进行共享。
- 线程之间共享全局变量可能会导致数据出现错误问题,可以使用线程同步方式来解决这个问题。
- 线程等待(join)
2.11 互斥锁
- 互斥锁的作用就是保证同一时刻只能有一个线程去操作共享数据,保证共享数据不会出现错误问题
- 使用互斥锁的好处确保某段关键代码只能由一个线程从头到尾完整地去执行
- 使用互斥锁会影响代码的执行效率,多任务改成了单任务执行
- 互斥锁如果没有使用好容易出现死锁的情况
2.12 死锁
- 使用互斥锁的时候需要注意死锁的问题,要在合适的地方注意释放锁。
- 死锁一旦产生就会造成应用程序的停止响应,应用程序无法再继续往下执行了。
2.13 进程和线程的对比
- 进程和线程都是完成多任务的一种方式
- 多进程要比多线程消耗的资源多,但是多进程开发比单进程多线程开发稳定性要强,某个进程挂掉不会影响其它进程。
- 多进程可以使用cpu的多核运行,多线程可以共享全局变量。
- 线程不能单独执行必须依附在进程里面
3.网络编程
3.1 IP地址的介绍
- P 地址的作用是标识网络中唯一的一台设备的
- IP 地址的表现形式分为: IPv4 和 IPv6
- 查看网卡信息:ifconfig
- 检查网络: ping
3.2端口和端口号
-
端口的作用就是给运行的应用程序提供传输数据的通道。
-
端口号的作用是用来区分和管理不同端口的,通过端口号能找到唯一个的一个端口。
-
端口号可以分为两类:
知名端口号
动态端口号
- 知名端口号的范围是0到1023
- 动态端口号的范围是1024到65535
3.3 TCP介绍
TCP 是一个稳定、可靠的传输协议,常用于对数据进行准确无误的传输,比如: 文件下载,浏览器上网。
3.4 socket的介绍
进程之间网络数据的传输可以通过 socket 来完成, socket 就是进程间网络数据通信的工具。
3.5 TCP网络应用程序开发流程
- TCP 网络应用程序开发分为客户端程序开发和服务端程序开发。
- 主动发起建立连接请求的是客户端程序
- 等待接受连接请求的是服务端程序
3.6 TCP客户端程序开发
- 导入socket模块
- 创建TCP套接字‘socket’
- 参数1: ‘AF_INET’, 表示IPv4地址类型
- 参数2: ‘SOCK_STREAM’, 表示TCP传输协议类型
- 发送数据‘send’
- 参数1: 要发送的二进制数据, 注意: 字符串需要使用encode()方法进行编码
- 接收数据‘recv’
- 参数1: 表示每次接收数据的大小,单位是字节
- 关闭套接字‘socket’表示通信完成
3.7 TCP服务端程序开发
- 导入socket模块
- 创建TCP套接字‘socket’
- 参数1: ‘AF_INET’, 表示IPv4地址类型
- 参数2: ‘SOCK_STREAM’, 表示TCP传输协议类型
- 绑定端口号‘bind’
- 参数: 元组, 比如:(ip地址, 端口号)
- 设置监听‘listen’
- 参数: 最大等待建立连接的个数
- 等待接受客户端的连接请求‘accept’
- 发送数据‘send’
- 参数: 要发送的二进制数据, 注意: 字符串需要使用encode()方法进行编码
- 接收数据‘recv’
- 参数: 表示每次接收数据的大小,单位是字节,注意: 解码成字符串使用decode()方法
- 关闭套接字‘socket’表示通信完成
3.8 TCP网络应用程序的注意点
- 当 TCP 客户端程序想要和 TCP 服务端程序进行通信的时候必须要先建立连接
- TCP 客户端程序一般不需要绑定端口号,因为客户端是主动发起建立连接的。
- TCP 服务端程序必须绑定端口号,否则客户端找不到这个 TCP 服务端程序。
- listen 后的套接字是被动套接字,只负责接收新的客户端的连接请求,不能收发消息。
- 当 TCP 客户端程序和 TCP 服务端程序连接成功后, TCP 服务器端程序会产生一个新的套接字,收发客户端消息使用该套接字。
- 关闭 accept 返回的套接字意味着和这个客户端已经通信完毕。
- 关闭 listen 后的套接字意味着服务端的套接字关闭了,会导致新的客户端不能连接服务端,但是之前已经接成功的客户端还能正常通信。
- 当客户端的套接字调用 close 后,服务器端的 recv 会解阻塞,返回的数据长度为0,服务端可以通过返回数据的长度来判断客户端是否已经下线,反之服务端关闭套接字,客户端的 recv 也会解阻塞,返回的数据长度也为0。
3.9案例-多任务版TCP服务端程序开发
-
编写一个TCP服务端程序,循环等待接受客户端的连接请求
while True: service_client_socket, ip_port = tcp_server_socket.accept()
-
当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞
while True: service_client_socket, ip_port = tcp_server_socket.accept() sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port)) sub_thread.start()
-
把创建的子线程设置成为守护主线程,防止主线程无法退出。
while True: service_client_socket, ip_port = tcp_server_socket.accept() sub_thread = threading.Thread(target=handle_client_request, args=(service_client_socket, ip_port)) sub_thread.setDaemon(True) sub_thread.start()
3.10 socket之send和recv原理剖析
不管是recv还是send都不是直接接收到对方的数据和发送数据到对方,发送数据会写入到发送缓冲区,接收数据是从接收缓冲区来读取,发送数据和接收数据最终是由操作系统控制网卡来完成。
4.HTTP协议和静态Web服务器
4.1 HTTP协议
- HTTP协议是一个超文本传输协议
- HTTP协议是一个基于TCP传输协议传输数据的
- HTTP协议规定了浏览器和 Web 服务器通信数据的格式
4.2 URL
- URL就是网络资源的地址,简称网址,通过URL能够找到网络中对应的资源数据。
- URL组成部分
- 协议部分
- 域名部分
- 资源路径部分
- 查询参数部分 [可选]
4.3 查看HTTP协议的通信过程
- 谷歌浏览器的开发者工具是查看http协议的通信过程利器,通过Network标签选项可以查看每一次的请求和响应的通信过程,调出开发者工具的通用方法是在网页右击选择检查。
- 开发者工具的Headers选项总共有三部分组成:
- General: 主要信息
- Response Headers: 响应头
- Request Headers: 请求头
- Response选项是查看响应体信息的
4.4 HTTP请求报文
- 一个HTTP请求报文可以由请求行、请求头、空行和请求体4个部分组成。
- 请求行是由三部分组成:
- 请求方式
- 请求资源路径
- HTTP协议版本
- GET方式的请求报文没有请求体,只有请求行、请求头、空行组成。
- POST方式的请求报文可以有请求行、请求头、空行、请求体四部分组成,注意:POST方式可以允许没有请求体,但是这种格式很少见。
4.5 HTTP响应报文
- 一个HTTP响应报文是由响应行、响应头、空行和响应体4个部分组成。
- 响应行是由三部分组成:HTTP协议版本 状态码 状态描述,最常见的状态码是200
4.6搭建Python自带静态Web服务器
- 静态Web服务器是为发出请求的浏览器提供静态文档的程序,
- 搭建Python自带的Web服务器使用python3 –m http.server 端口号 这个命令即可,端口号不指定默认是8000
4.7静态Web服务器-返回固定页面数据
-
编写一个TCP服务端程序
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) # 循环接受客户端的连接请求 while True: conn_socket, ip_port = tcp_server_socket.accept()
-
获取浏览器发送的http请求报文数据
client_request_data = conn_socket.recv(4096)
-
读取固定页面数据,把页面数据组装成HTTP响应报文数据发送给浏览器。
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body conn_socket.send(response_data)
-
HTTP响应报文数据发送完成以后,关闭服务于客户端的套接字。
conn_socket.close()
4.8静态Web服务器-返回指定页面数据
-
获取用户请求资源的路径
request_list = client_request_conent.split(” ”, maxsplit=2) request_path = request_list[1]
-
根据请求资源的路径,读取请求指定文件的数据
with open("static" + request_path, "rb") as file: file_data = file.read()
-
组装指定文件数据的响应报文,发送给浏览器
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body conn_socket.send(response_data)
-
判断请求的文件在服务端不存在,组装404状态的响应报文,发送给浏览器
try: # 打开指定文件,代码省略... except Exception as e: conn_socket.send(404响应报文数据)
4.9 静态Web服务器-多任务版
-
当客户端和服务端建立连接成功,创建子线程,使用子线程专门处理客户端的请求,防止主线程阻塞。
while True: conn_socket, ip_port = tcp_server_socket.accept() # 开辟子线程并执行对应的任务 sub_thread = threading.Thread(target=handle_client_request, args=(conn_socket,))
-
把创建的子线程设置成为守护主线程,防止主线程无法退出。
# 开辟子线程并执行对应的任务 sub_thread = threading.Thread(target=handle_client_request, args=(conn_socket,)) sub_thread.setDaemon(True) # 设置守护主线程 sub_thread.start()
4.10 静态Web服务器-面向对象开发
-
把提供服务的Web服务器抽象成一个类(HTTPWebServer)
class HttpWebServer(object):
-
提供Web服务器的初始化方法,在初始化方法里面创建socket对象
def __init__(self): # 初始化服务端套接字,设置监听,代码省略..
-
提供一个开启Web服务器的方法,让Web服务器处理客户端请求操作。
def start(self): while True: service_client_socket, ip_port = self.tcp_server_socket.accept() # 连接建立成功,开辟子线程处理客户端的请求 sub_thread = threading.Thread(target=self.handle_client_request, args=(service_client_socket,)) sub_thread.start()
4.11 静态Web服务器-命令行启动动态绑定端口号
-
获取执行python程序的终端命令行参数
sys.argv
-
判断参数的类型,设置端口号必须是整型
if not sys.argv[1].isdigit(): print("启动命令如下: python3 xxx.py 9090") return port = int(sys.argv[1])
-
给Web服务器类的初始化方法添加一个端口号参数,用于绑定端口号
def __init__(self, port): self.tcp_server_socket.bind((“”, port))