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
))