Python人工智能总目录
文章目录
3、Python-网络编程
Day01
内容安排
1. 网络编程
2. 进程线程
3. 正则表达式
4. mongodb数据库
5. git使用
6. 项目
网络编程
网络功能 : 数据的传输
ISO(国际标准化组织)
1. OSI七层模型 --> 网络通信标准化流程
OSI七层模型 --> 网络通信标准化流程
应用层 : 提供用户服务,具体功能有程序体现
表示层 : 数据的压缩优化和加密
会话层 : 建立应用连接,选择合适的传输服务
传输层 : 提供传输服务,进行流量控制
网络层 : 路由选择,网络互连
链路层 : 进行数据交换,控制具体消息收发,链路连接
物理层 : 提供物理硬件传输,网卡,接口设置,传输介质
2.OSI七层模型优势: 1. 建立了统一的网络工作流程
2. 每个层次功能清晰,各司其职
3. 降低了耦合度,方便了开发流程
3.cookie:
高内聚: 模块功能尽可能单一,不要相互掺杂
低耦合: 模块之间的关联影响尽可能少
2. 四层模型 和 五层模型
1.四层模型 (TCP/IP模型): 应用层 传输层 网络层 物理链路层
* 将应用层,表示层,会话层统一为应用层,便于开发实践
2.五层模型: 应用层 传输层 网络层 链路层 物理层
3. 数据的传输流程
数据的传输流程
1. 发送端由应用层逐层根据协议添加首部信息,最终在物理层实现发送
2. 发送的消息经过中间多个节点转发到达目标主机
3. 目标主机根据协议逐层解析首部,最终到达应用层获取数据
网络协议:网络通信双方都遵守的规定,包括建立什么数据结构,消息结构,首部内容等
4. 网络编程基本概念
网络编程基本概念
1.网络主机: 在网络中标识一台主机的标志
本地使用 : 'localhost'
'127.0.0.1'
网络使用 : '192.168.56.131'
'0.0.0.0'
ifconfig : 查看本地网络信息
2.IP地址 : 在网络上查找一台主机的网络位置
IPv4 : 点分十进制 192.168.1.2 每部分取值:0--255
IPv6 : 扩充地址的范围
ping [ip] : 网络连接测试
特殊IP
127.0.0.1 本机测试IP
0.0.0.0 本机自动获取能够使用的网卡IP
192.168.1.0 表达一个网段
192.168.1.1 表示网关地址
192.168.1.255 广播地址
3.域名 : 网络服务器的别名
作用: 方便记忆,表达一定的含义
4.端口号 port
端口号是网络地址的一部分,用于区分主机上不同的网络应用
* 在一个系统中应用监听的端口不重复
取值范围: 1 -- 65535
1 -- 255 一些众所周知的公共程序端口
256 -- 1023 系统应用端口
1024 -- 65535 自用端口
5.网络字节序 : 网络上数据传输的排列方式
5. 传输层服务
传输层服务
1.面向连接的传输服务 (基于TCP协议的数据传输)
传输特征 : 提供可靠的数据传输,可靠性指的是传输过程中无丢失,无失序,无差错,无重复
实现手段 : 在通信前需要建立通信连接,通信结束需要断开连接
连接过程 (三次握手)
1. 客户端向服务端发起连接请求
2. 服务端收到客户端请求报文(消息序列号),回复报文消息表示可以连接
3. 客户端收到服务端回复,再从发送报文最终建立连接
连接断开 (四次挥手)
1. 主动方发送报文提出断开连接
2. 被动方接收到断开请求,立即返回消息表示开始准备断开
3. 被动方处理消息完毕,完成断开准备,再次发送报文表示可以断开
4. 主动方收到断开指令,发送报文最终确认断开
适用情况: 对数据传输有准确性的要求,传输文件较大,需要确保传输可靠性
比如 : 网页获取,文件下载,邮件收发
2.面向无连接的传输服务 (基于UDP协议的传输)
传输特征: 不保证传输的可靠性,数据传输不需要提前建立连接
适用情况: 网络情况较差,对传输可靠性要求不高.
比如:网络视频,群聊,广播
3.要求:
1. OSI七层模型介绍一下,tcp/ip模型是什么
2. tcp服务和udp服务有什么区别,tcp udp是哪层协议
3. 简单描述下三次握手和四次挥手过程
6.socket 模块
socket 模块
功能 : python的标准库模块,提供网络编程的一系列接口功能
简单函数示例:
获取计算机名
socket.gethostname()
'tedu'
通过域名获取主机地址
socket.gethostbyname('www.baidu.com')
'119.75.217.109'
获取指定服务的端口
socket.getservbyname('ssh')
22
查看端口对应的服务程序
socket.getservbyport(22)
'ssh'
查看指定服务器信息 (服务器名,别名,ip)
socket.gethostbyaddr('localhost')
('localhost', [], ['127.0.0.1'])
将点分十进制地址转换为二进制
socket.inet_aton('192.168.1.2')
b'\xc0\xa8\x01\x02'
将二进制地址转换为点分十进制
socket.inet_ntoa(b'\xc0\xa8\x01\x02')
'192.168.1.2'
7. 套接字
1.套接字: 实现网络编程,进行数据传输的一种编程方案,通过socket模块提供的接口函数进行组合搭配实现
2.套接字分类:
1.流式套接字 (SOCK_STREAM)
特征 : 面向连接的传输服务,能够保证传输可靠性,是基于tcp请求的一种套接字.数 据传输使用字节流传输
2.数据报套接字 (SOCK_DGRAM)
特征 : 面向无连接的传输服务,不保证传输可靠,是基于udp请求的一种套接字,使用 数据报进行传输
8. tcp流式套接字编程
1.服务端流程
服务端流程
1. 创建套接字
sockfd = socket(socket_family=AF_INET,
socket_type=SOCK_STREAM,
proto=0)
功能 : 创建套接字
参数 : socket_family : 地址族类型 AF_INET->ipv4
socket_type: 套接字类型
SOCK_STREAM 流式
SOCK_DGRAM 数据报
proto: 通常为0
返回值 : 套接字对象
2. 绑定服务器地址
sockfd.bind(addr)
功能: 绑定服务器网络地址
参数: 元组 (ip,port) --> ('127.0.0.1',8888)
3. 设置套接字监听
sockfd.listen(n)
功能 : 将套接字设置为监听套接字并创建监听队列
参数 : 监听队列大小
* 一个监听套接字能够连接多个客户端套接字
4. 等待处理客户端连接
connfd,addr = sockfd.accept()
功能 : 阻塞等待处理客户端连接请求
返回值: connfd 生成的新的客户端连接套接字
addr 连接的客户端的地址
* 阻塞函数:程序运行中遇到阻塞函数则暂停执行,知道阻塞条件满足后再继续执行
5. 收发消息
data = connfd.recv(buffersize)
功能: 接收tcp消息
参数: 每次最多接收消息大小(字节)
返回值: 接收到的内容
n = connfd.send(data)
功能: 发送tcp消息
参数: 要发送的内容 (bytes格式)
返回值: 发送的字节数
str --> bytes encode()
bytes --> str decode()
6.关闭套接字
sockfd.close()
功能: 关闭套接字
2. 客户端流程
客户端流程:
1. 创建套接字 (必须相同类型套接字才能通信)
2. 请求连接
sockfd.connect(addr)
功能: 连接服务端套接字
参数: 服务端地址
3. 消息收发
4. 关闭套接字
作业:
1. 对理论问题进行总结
2. 将tcp 服务端客户端代码改为可以循环收发
3. 复习open文件处理方法
前情回顾
1. osi七层模型 tcp/ip模型
2. 三次握手和四次挥手
3. tcp udp区别
网络概念 : 主机 IP地址 端口 域名
套接字 : 网络编程方式
流式套接字 : tcp
数据报套接字: udp
tcp套接字 :
服务端
socket()-->bind()-->listen()-->accept()-->
recv()/send()-->close()
客户端
socket()-->connect()-->recv()/send()-->close()
Day02
1. tcp 传输特征
tcp 传输特征
1. 当一端退出时,如果连接端阻塞在recv,此时recv会立即结 束阻塞返回空字串.
2. 如果连接端关闭,再调用send企图发送时会出现Broken Pipe异常
网络收发缓冲区
1. 减少和磁盘的交互次数
2. 协调收发速度
* send和recv实际是向缓冲区发送,从缓冲区接收
* 当缓冲区满时send会阻塞,接收缓冲区空时recv阻塞
2. tcp粘包
tcp粘包
1. tcp套接字是以字节流的方式传输消息,没有消息边界
2. 多次发送的内容被一次接收
影响 : 如果每次发送内容是一个独立含义的个体,此时如果 粘包会产生影响
处理粘包:
1. 人为添加消息边界
2. 将消息结构化
3. 控制消息发送速度
3. 基于UDP套接字
1. UDP服务端
基于UDP套接字服务端
1. 创建数据报套接字
sockfd = socket(AF_INET,SOCK_DGRAM)
2. 绑定地址
sockfd.bind(addr)
3. 消息收发
data,addr = sockfd.recvfrom(buffersize)
功能: 接收UDP消息
参数: 每次最多接收消息的大小
返回值: data 接收到的消息
addr 消息发送方的地址
n = sockfd.sendto(data,addr)
功能 : 发送udp消息
参数 : data 要发送的内容
addr 目标地址
返回值:发送字节数
4. 关闭套接字
sockfd.close()
2. UDP客户端
UDP客户端:
1. 创建UDP套接字
2. 消息收发
3. 关闭套接字
cookie
import sys
sys.argv属性 : 用于获取命令行传入参数
4. tcp套接字和udp套接字区别
tcp套接字和udp套接字区别
1. tcp套接字以字节流方式传输,数据报套接字以数据报形 式传输
2. tcp传输会有粘包,udp不会(有消息边界)
3. tcp传输保证传输可靠性,udp则会有部分消息丢失的可能
4. tcp需要listen accept 保证连接,udp不需要
5. tcp使用send,recv收发消息,udp使用sendto recvfrom
补充函数:
sendall(data)
功能 : 发送tcp消息
参数 : 发送的内容bytes
返回值 : 发送成功返回None 失败产生异常
5. 套接字对象属性
套接字对象属性:
1.sockfd.family 获取套接字地址族类型
2.sockfd.type 获取套接字类型
3.sockfd.getsockname() 获取套接字绑定地址
4.sockfd.fileno() 获取套接字的文件描述符
文件描述符 : 系统中给每一个IO操作分配的唯一的整数,用
于管理IO.这个整数即这个IO的文件描述符
5.sockfd.getpeername() 获取连接端的地址信息
6.sockfd.setsockopt(level,option,value)
功能 : 设置套接字选项,丰富或者修改套接字属性功能
参数 : level 要设置的套接字选项类别 SOL_SOCKET
option 选择每个类别中具体的选项
value 要设置的值
7.sockfd.getsockopt(level,option)
功能 : 获取套接字选项值
参数 : level 要获取的套接字选项类别
option 选择每个类别中具体的选项
返回值: 获取的值
6.UDP通信 和 TCP通信
1.UDP通信--->广播
广播 : 一点发送,多点接收
广播地址: 192.168.56.255 (通常为每个网段的最大地址)
设置可以发送接收广播
s.setsockopt(SOL_SOCKET,SO_BROADCAST,1)
广播风暴 : 一个网络中存在大量广播会占有较多带宽,对网络产生影响
2.TCP通信 --> http协议通信
http协议 (超文本传输协议) 应用层协议
用途 : 网页的获取
数据的传输
特点 :
1. 应用层协议,传输层采用tcp方式收发消息
2. 简单,灵活,很多语言都有http协议接口
3. 无状态的协议,协议本身不要求记录传输数据
4. http1.1 支持持久连接
7. 网页请求过程
网页请求过程:
1. 客户端(浏览器)通过tcp传输,发送http请求给服务器
2. 服务器收到http请求后进行解析
3. 服务端处理具体请求内容,整理需要的数据
4. 将数据以http响应的格式回发给客户端(浏览器)
5. 浏览器接收响应,显示内容
1.http请求 (request)
#http请求 (request)
请求格式
请求行 : 具体的请求类别和请求内容
格式 : GET / HTTP/1.1
请求类别 请求内容 协议版本
请求类别 每种类别代表作不同的事情
GET 获取网络资源
POST 提交一定的信息,得到反馈
HEAD 获取网络资源的响应头
PUT 更新服务器资源
DELETE 删除服务器资源
CONNECT 预留
TRACE 测试
OPTIONS 获取服务器信息
请求头 : 对请求内容的基本描述
Accept-Encoding: gzip, deflate, br
Accept-Language: zh-CN,zh;q=0.9
Cache-Control: max-age=0
Connection: keep-alive
空行
请求体 : 请求参数和提交内容
2. http响应(response)
#http响应(response)
1.响应格式
响应行 : 反馈响应的基本情况
格式: HTTP/1.1 200 OK
协议版本 响应码 附加信息
响应码: 1xx 提示信息,请求被接收
2xx 响应成功
3xx 响应需要进一步操作,重定向
4xx 客户端错误
5xx 服务器错误
响应头 : 对响应内容的描述信息
Cache-Control: private
Connection: Keep-Alive
Content-Encoding: gzip
Content-Type: text/html
空行
响应体 : 回复给客户端的具体内容
要求 :
1. 知道http协议的作用
2. 了解网页访问的基本流程
3. 掌握http协议 请求和响应的格式
4. 知道http请求的基本类型和响应码的含义
练习 : 编写一个tcp客户端一个服务端,完成文件的传输
作业 : 写一个简易的httpserver程序 ,将一个网页发送给浏览器显示
前情回顾
1. tcp传输特征
* 传输中接收和发送特征
* 网络缓冲区
* 粘包
2. UDP传输
服务端 创建套接字 --> 绑定地址-->发送接收-->关闭
客户端 创建套接字-->收发消息 --> 关闭
3. 套接字属性
fileno()
getpeername()
setsockopt()
4. 广播
5. HTTP协议
* 网页获取过程
* http请求
格式 : 请求行 请求头 空行 请求体
请求行: GET / HTTP/1.1
主页: index.html
* http响应
格式 : 响应行 响应头 空行 响应体
响应行: HTTP/1.1 200 OK
Day03
1. IO (input output)
IO (input output)
在内存中存在数据交互的操作认为是IO操作
和终端交互 : input print
和磁盘交互 : read write
和网络交互 : recv send
IO密集型程序: 在程序执行中有大量IO操作,而较少的cpu运算.消耗cpu少,效率低,耗时长
计算密集型程序 : 在程序运行中,IO操作较少,cpu计算较多,cpu消耗大,运行速度快
2. IO模型
IO模型: 阻塞IO 非阻塞IO IO多路复用 事件IO 异步IO ...
1.阻塞IO
1.阻塞IO:
阻塞IO是IO的默认形态,是效率很低的一种IO
阻塞情况:
* 因为某种条件没有达成造成的函数阻塞
e.g. accept input recv
* 处理IO的时间较长产生的阻塞行为
e.g. 网络延迟,大文件的读写
2. 非阻塞IO
2.非阻塞IO:
将原本阻塞的函数通过属性的设置改变阻塞行为,变为非阻塞
sockfd.setblocking(bool)
功能: 设置套接字为非阻塞IO
参数: 默认True 表示套接字调用阻塞函数时为阻塞状态
设置为False则表示非阻塞状态
超时检测,即设置一个最长阻塞等待时间,超时后即不再阻塞
sockfd.settimeout(sec)
功能:设置套接字超时时间
参数: 设置的时间, 秒
* 超时检测不能和非阻塞通用,否则超时没有意义
3. IO多路复用
IO多路复用
定义: 同时监控多个IO事件,选择其中能够执行的IO进行IO事件处理. 以此形成可以同时操作多个 IO的行为模式,避免一个IO阻塞造成其他IO均无法执行的情况.
IO事件就绪 : IO已经发生,内核需要交给应用程序处理
具体方法:
import select
select : windows linux unix
poll : linux unix
epoll : linux
3 . IO多路复用
1. select 方法
select 方法
rs,ws,xs=select(rlist, wlist, xlist[, timeout])
功能: 监控IO事件,阻塞等待IO事件发生
参数: rlist 列表 存放需要等待条件发生的IO事件
wlist 列表 存放需要主动处理的IO事件
xlist 列表 当发生异常你需要处理的IO事件
timeout 超时时间
返回值: rs 列表 rlist中准备就绪的IO
ws 列表 wlist中准备就绪的IO
xs 列表 xlist中准备就绪的IO
注意 : 1. IO多路复用占用计算机资源较少,效率较高
2. wlist 中如果有IO则select立即返回处理
3. 在IO处理过程中不要出现死循环,影响IO 监控
位运算
& 按位与
| 按位或
^ 按位异或
<< 左移
>> 右移
11 1011
14 1110
11&14 1010 一0则0
11|14 1111 一1则1
11^14 0101 相同为0不同为1
11<<2 101100 向左移动右侧补0
14>>2 11 向右移动去掉低位
2. poll方法
poll方法
1.p = select.poll()
功能 : 创建poll对象
返回值: poll对象
p.register(fd,event)
功能 : 注册要关注的IO
参数 : fd 要关注的IO对象
event 要关注的事件
常用事件类型: POLLIN 读IO rlist
POLLOUT 写IO wlist
POLLERR 出错IO xlist
POLLHUP 断开连接事件
e.g. p.register(sockfd,POLLIN|POLLERR)
2.p.unregister(fd)
功能: 取消关注的IO
参数: IO对象或者文件描述符
events = p.poll()
功能 : 阻塞监控IO事件发生
返回值 : events 是一个列表
[(fileno,event),()....]
每个就绪IO对应一个元组,元组中为该IO的fileno和就绪事件
* 返回值中没有IO对象,所以通过fileno配合IO对象字典查 找
{fileno:io_obj}
3.poll_server步骤:
1. 创建套接字
2. 设置套接字为关注
3. 建立fileno查找字典
4. 循环监控IO
5. 处理发生的IO
作业 : 熟练io模型特点
熟悉io多路复用原理
熟练 select 和 poll
复习 类的使用 __init__ 继承 super
前情回顾
1. httpserver v1.0
2. IO模型
阻塞IO : 默认IO行为 效率低
非阻塞IO: 设置非阻塞属性,超时检测
setblocking()
settimeout()
IO多路复用:同时监控多个IO事件,选择可以执行的执 行
select()
poll()
Day04
IO多路复用
3. epoll方法
epoll方法
使用方法 : 基本同poll相同
* 将生成对象函数改为 epoll
* 将所有关注IO事件类型变为EPOLL类型
epoll特点 :
* epoll是linux的专属多路复用方法
* epoll效率比select和poll要高
* epoll可以监控更多的IO (select 最多1024)
* epoll支持更多的触发事件类型(EPOLLET边缘触发)
1. 结构化数据
结构化数据
import struct
原理 : 将部分数据类型放在一起,转换成bytes格式数据包,并且可以按照指定格式解析bytes数 据包
1.struct.Struct(fmt)
功能:生成struct格式包对象
参数: fmt 定制的数据结构组成
e.g. 1 b'Jame' 1.75 #要发送的一组数
st = Struct("i4sf") #生成对应数据格式对象
常用fmt int i
bytes ns (n代表几个字符)
float f
2.st.pack(v1,v2,v3....)
功能 : 将数据按照指定格式打包为bytes
参数 : 要打包的数据
返回值 : 打包后的bytes字串
3.st.unpack(bytes)
功能: 将bytes格式数据包解析
参数: 要解析的数据包
返回值: 数据元组
pack()和unpack()可以通过struct模块直接调用
struct.pack(fmt,v1,v2....)
struct.unpack(fmt,data)
2. 本地套接字
本地套接字
功能 : 本地两个程序之间利用套接字进行通信的一种方法
cookie:
linux 文件类型 b(块设备文件)
c(字符设备文件)
d (目录)
- (普通文件)
l (链接文件)
s (套接字文件)
p (管道文件)
1. 创建本地套接字
sockfd = socket(AF_UNIX,SOCK_STREAM)
2. 绑定本地套接字文件
sockfd.bind(path)
3. 监听
sockfd.listen()
4. 连接
sockfd.accept()
5. 消息收发
recv send
3. 多任务编程
多任务编程:
1.意义 : 充分利用计算机的多核资源,同时运行多个任务,以提高程序的执行效率
2.实现方法 : 多进程 多线程
3.并发 : 同时处理多个任务,内核在任务间不断的切换达到好像多个任务同时被执行的效果.实际 每一时刻只有一个任务占有cpu
4.并行 : 多个任务利用计算机多核资源在同时执行,此时多个任务间是并行关系
4. 进程(process)
定义 : 程序在计算机中的一次运行过程
程序 : 是一个可执行的文件,是静态的,占有磁盘
进程 : 进程是一个动态过程,占有计算机资源,有生命周期
1. 进程的诞生
进程的诞生
1. 用户空间通过启动执行程序,或者调用进程创建接口发起进程创建请求
2. 操作系统接收用户请求,开始创建进程
3. 操作系统分配计算机资源,确定进程状态,开辟空间等
4. 操作系统将进程提供给用户使用
2. cpu时间片
cpu时间片 : 如果一个进程占有cpu内核则称这个进程在cpu时间片上
3.进程的信息及其查看
1.PCB(进程控制块) : 在内存中开辟的一块空间,存放进程的基本信息.也是操作系统调用进程的重 要标志
2.进程ID(PID) : 系统为每个进程分配一个不重复的ID号,是该进程在系统中的标识
查看进程信息 : ps -aux
3.父子进程 : 系统中每一个进程都有唯一的父进程,可以有0个或者多个子进程
查看进程树 : pstree
4. 进程状态
进程状态 :
1.三态
就绪态 : 进程具备执行条件,等待系统分配cpu
运行态 : 进程占有cpu时间片运行
等待态 : 进程暂时阻塞,不具备执行条件
2.五态
新建态 : 创建一个新的进程,获取资源的过程
终止态 : 进程结束,释放资源的过程
查看进程状态: ps -aux STAT列
S 等待态
D 等待态
T 暂停态
R 运行态
Z 僵尸
5. 进程优先级
进程优先级
作用 : 决定进程的优先权限和占有资源的优先程度
linux 优先级范围: -20---19 数字越小优先级越高
1.查看优先级: top
2.以某个优先值运行 : nice -num process
e.g. 以9运行进程
nice -9 python3 while.py
< 有较高优先级的
N 有较低优先级的
+ 前台进程
s 会话组组长
l 有进程链接
3.后台运行进程: 运行命令后加 &
e.g. python3 while.py &
4.杀死一个进程: kill -9 PID
要求:
1. 什么是进程,进程和程序区别
2. 进程有哪些状态,各种状态如何转换
6. 进程运行特征
进程运行特征:
1. 进程可以使用计算机多核资源
2. 进程是计算机分配资源的最小单位
3. 进程之间的运行互不干扰,相互独立
4. 每个进程空间独立,有自己的空间资源
7. 进程创建
进程创建:
import os
pid = os.fork()
功能 : 创建新的进程
返回值: 失败 返回一个负数
成功 原进程中返回新进程的PID号
新进程中返回0
作业 : 理解fork的使用
前情回顾
1. epoll方法
2. struct 模块
3. 本地套接字 AF_UNIX
4. 多任务编程
并发 并行
5. 进程概念
进程 PCB 时间片 父子进程 PID
进程状态 : 就绪 运行 等待
6. 创建进程 os.fork()
Day05
多进程
1. 关于 fork
关于 fork:
* 子进程从fork的下一句开始执行
* 父子进程各自独立运行,运行顺序不一定
* if结构几乎是fork的固定搭配通过父子进程返回值的区别, 使其执行不同的代码
* 子进程会复制父进程全部代码段和内存空间,包括fork前所 开辟的空间
* 父子进程空间互不影响,各自修改各自空间内容
* 子进程也有自己独立的内容,比如 PID 指令集 PCB等
2. 进程函数
进程函数:
os.getpid()
功能: 获取当前进程的PID号
返回值 : 返回PID
os.getppid()
功能: 获取父进程的PID号
返回值 : 返回PID
os._exit(status)
功能: 退出进程
参数: 整数 表示进程的退出状态
sys.exit([status])
功能: 退出进程
参数: 整数 表示进程退出状态, 默认为0
字符串 表示进程退出时打印该字串
3. 孤儿进程 和 僵尸进程
1.孤儿进程 : 父进程先于子进程退出,此时子进程就成为孤儿进程
* 孤儿进程会被系统进程收养,即该系统进程成为孤儿进程新的父进程
2.僵尸进程 : 子进程先于父进程退出,且父进程没有处理子进程退出行为,此时子进程就会成为僵尸进程
* 僵尸进程虽然结束但是会存留部分进程信息在内存中,大量 的僵尸进程会消耗系统资源, 因此应该避免僵尸进程产生
3.如何处理僵尸进程:
* 二级子进程
pid,status = os.wait()
功能 : 父进程中阻塞等待处理子进程的退出
返回值: pid 退出的子进程的PID号
status 子进程退出状态
pid,status = os.waitpid(pid,option)
功能 : 父进程中处理子进程的退出
参数 : pid -1 表示等待任意子进程退出
>0 表示等待对应PID的子进程退出
option 0 表示阻塞等待
WNOHANG 表示非阻塞
返回值: pid 退出的子进程的PID号
status 子进程退出状态
4. 群聊聊天室
群聊聊天室:
功能 : 类似qq群聊
1. 进入聊天室需要输入姓名,姓名不能重复
2. 进入聊天室会向其他成员发送通知
xxx 进入了聊天室
3. 一个人发消息,其他人都会收到
xxx 说 : xxxxxxxxxxx
4. 某人退出聊天室,其他人也会收到通知
xxx 退出了聊天室
5. 管理员可以从后台发送消息,此时群里人都收到
管理员 说:xxxxxxx
1.技术分析
发消息 : udp套接字
成员存储 : 服务端 {name:addr} [(name,addr),()]
消息发送模式 : 转发, 消息先发给服务器,服务器转发给其他成员
管理员 : 服务端 发送内容,其他人接收
保证收发消息互不影响 : 使用多进程
2.整体设计
1. 封装方式
2. 编写流程 先确保通信实现 再逐个功能实现
3. 测试 实现一个功能测试一个功能
3.具体功能实现
网络通信
服务端: 创建udp套接字,绑定地址
客户端: 创建套接字
进入聊天室
客户端: 输入用户名
将用户名发送给服务端
得到一个反馈
如果不允许进入则重新输入姓名
如果允许进入聊天室则进入聊天
创建新的进程一个用于接收
一个用于发送
服务端: 接收姓名
判断姓名是否存在
如果存在返回不许进入
如果不存在则将用户加入存储结构
通知其他人登录信息
聊天:
服务端 : 接收消息
转发消息
客户端 : 输入消息
发送消息
退出:
服务端 : 接收退出请
发送通知给其他人
给退出者发送EXIT
从user删除用户
客户端 : 发送提出信息
父子进程退出
作业 : 将一个文件使用父子进程进行复制父子进程分别复制文件的
上下两部分到一个新的文件中按字节分割上下两部分
前情回顾
1. 进程相关函数
os.getpid()
os.getppid()
os._exit()
sys.exit()
2. 孤儿进程 和 僵尸进程
处理僵尸进程 wait() waitpid()
创建二级子进程
3. 聊天室
确定需求---> 基本技术分析-->整体设计-->功能分析-->编码实现 --> 代码测试
Day06
注意 :
如果子进程从父进程继承对象,则父子进程使用此对象可能会相互影响
但是如果对象是子进程创建后,在各自进程中生成的则一定没有影响
1. multiprocessing 模块创建进程
multiprocessing 模块创建进程
1. 将需要执行的进程事件封装为函数
2. 使用模块中的Process 类生成进程对象,并关联相关函数
3. 可以通过对象属性设置进程信息
4. 通过进程对象启动进程,此时自动运行进程函数
5. 回收进程
1.Process() #创建进程
功能 : 创建进程对象
参数 : target 绑定的目标函数
name 进程名 默认Process-1
args 元组,按位置给target函数传参
kwargs 字典,按照键值对给target函数传参
2.p.start() #启动进程
功能 : 启动进程
* target绑定的函数会自动执行,此时进程真正被创建
3.p.join([timeout]) #阻塞等待并回收进程
功能: 阻塞等待回收进程
参数: 超时时间
* 使用multiprocessing创建进程,同样子进程复制父进程全 部代码空间,父子进程互不影 响,各自运行,子进程相当于只 执行绑定函数
* join可以处理僵尸进程
* multiprocessing 中父进程可以更方便创建多个进程执行 多个事件.父进程往往将事件交 由子进程完成
2.进程对象属性
进程对象属性:
p.name 进程名称
p.pid 进程号
p.is_alive() 进程状态(查看是否在生命周期)
p.daemon
默认是False 表示主进程退出,不会影响子进程继续运行
如果设置为True 此时主进程退出,子进程也会结束
* 要求在start()前设置
3.自定义进程类
自定义进程类
适用情况 : 使用类将一系列功能进行封装,通过调用类中的 方法完成较复杂的功能
步骤 :
1. 继承Process类
2. 编写自己的__init__添加属性
使用super重新加载父类__init__方法
3. 重写run方法,完成功能逻辑调用
使用:
1.使用自定义类实例化对象
2.使用实例化对象调用 start() 则创建新的进程,自动运行 run方法
3. 使用对象调用join()则回收进程
4. 多进程的优缺点
多进程:
优点 : 可以使用计算机多核资源,同时运行多个任务,提高运行效率
缺点 : 进程的创建和删除过程需要消耗较多的系统资源.大量进程频繁的创建删除会给系统带来压力
5. 进程池技术
进程池技术:
1.产生原因 : 应对大量任务需要多进程完成,需要频繁创建删除进程的情况
2.原理 : 创建一定量的进程作为进程池,用来处理事件.
事件处理完毕后,进程不退出,而是继续等待处理其他事件.直到所有待
处理事件处理完毕后统一销毁进程.增加了进程的重复利用,降低资源消耗.
3.使用方法 :
1. 创建进程池,放入适当的进程
2. 将要做的事件封装为函数,放入进程池等待队列
3. 进程池中的进程会不断执行队列中的事件直到全部被执行
4. 关闭进程池,回收进程
from multiprocessing import Pool
1.pool = Pool(processes)
功能 : 创建进程池对象
参数 : 指定进程池中进程数据量,默认根据系统自动判定
2.pool.apply_async(func,args,kwds)
功能: 放入要执行的事件函数
参数 : func 事件函数
args 元组 给函数按位置传参
kwds 字典 给函数按键值传参
返回值 :返回函数事件对象,调用get()可以获取func返回值
3.pool.apply(func,args,kwds)
功能: 放入要执行的事件函数
参数 : func 事件函数
args 元组 给函数按位置传参
kwds 字典 给函数按键值传参
4.pool.map(func,iter)
功能: 将函数事件放入进程池执行
参数: func 要执行的函数
iter 可迭代对象,用于给func传参
返回值: 函数的返回值列表
5.pool.close()
功能 : 关闭进程池,无法再添加新的事件
6.pool.join()
功能 : 阻塞等待回收进程池
6. 进程间通信 (IPC)
1.原因 : 进程空间相对独立,资源无法直接获取.此时在不同的进程间需要进行消息传输,即进程间通信
2.进程间通信方式: 管道 消息队列 共享内存 信号 信号量 套接字
1. 管道通信 (pipe)
#道通信 (pipe):
通信原理 : 在内存中开辟管道空间,生成管道操作对象,进
程间使用同一组管道对象进行读写实现通信
from multiprocessing import Pipe
fd1,fd2 = Pipe(duplex = True)
功能 : 创建管道
参数 : 默认表示双向管道
False表示单项管道
返回值: 表示管道两端的读写对象
如果是双向管道,则fd1,fd2均可读写
单向管道,则fd1只读,fd2只写
fd.recv()
功能 : 从管道读取内容
返回值 : 读到的内容
* 如果管道为空则阻塞
fd.send(data)
功能 : 向管道写入内容
参数 : 要写入的内容
* 可以写入Python格式数据
2.消息队列 (queue)
#消息队列 (queue):
队列 : 先进先出
通信原理 : 在内存中建立队列模型,进程通过队列对象将消
息存入到队列,或者从队列取出消息,完成进程
间通信.被先放入的消息一定先取出
from multiprocessing import Queue
1.q = Queue(maxsize=0)
功能 : 创建消息队列
参数 : 表示队列中最多存放多少消息
返回值 : 队列对象
2.q.put(data,[block,timeout])
功能: 向队列存入消息
参数: data 要存入的内容 Python 数据
block 默认队列满会阻塞,设置为False则为非阻塞
timeout 超时检测
3.data = q.get([block,timeout])
功能 : 从队列中获取消息
参数 : block 默认队列空阻塞,设置False为非阻塞
timeout 超时检测
返回值 : 获取到的数据
4.q.full() 判断队列是否为满
5.q.empty() 判断队列是否为空
6.q.qsize() 获取队列中消息个数
7.q.close() 关闭队列
作业 : 1. 整理 multiprocessing 和fork创建进程方法
2. 复习tcp和udp通信
3. http协议 mysql操作
前情回顾
1. multiprocessing模块
创建进程 : Process(target,args,kwargs)
start()
join()
进程对象属性 : p.name p.pid p.daemon p.is_alive()
自定义进程类 : 继承Process 重写run方法
进程池 : 大量进程事件需要处理,此时进程池可以避
免频繁创建进程带来的系统消耗.
Pool() 创建进程池对象
apply_async(func,args,kwds) 放入进程池事件
close() 关闭进程池
join() 回收进程池
map() 使用迭代对象为指定函数传参后加入进程池
2.进程间通信
管道 : Pipe() fd.recv() fd.send()
消息队列 : Queue() q.get() q.put()
q.full() q.empty() q.qsize() q.close()
Day07
进程间通信
3. 共享内存
#共享内存:
通信原理: 在内存中开辟一个区域,对多进程可见,进程可以
写入内容或读取内容,但是每次写入的内容都会
覆盖之前的
from multiprocessing import Value,Array
1.obj = Value(ctype,data)
功能 : 开辟共享内存
参数 : ctype : 字符串 表示共享内存中的数据类型
常用格式: int-->'i'
float --> 'f'
char(bytes) ---> 'c'
data : 初始化存入数据
obj.value 属性 即共享内存中的值.对该属性的读取和修改即修改共享内存
2.obj = Array(ctype,obj)
功能 : 创建共享内存
参数 : ctype 要存储的数据类型
obj 列表(字符串) 表示共享内存中初始数据
数字 空间结构的大小
返回值 : 共享内存对象
* 可以通过循环遍历或者[]序列号方式获取共享内存值,或改写共享内存值
* 如果共享内存中是字节串,可以通过 obj.value 获取该字串
管道 | 消息队列 | 共享内存 | |
---|---|---|---|
开辟空间 | 内存 | 内存 | 内存 |
读写方式 | 两端读写 | 先进先出 | 覆盖之前内容 |
效率 | 一般 | 一般 | 较高 |
使用特点 | 多用于父子进程 | 第三方库较多 | 操作需要注意争夺内存资源 |
4. 信号量(信号灯)
#信号量(信号灯):
原理 : 给定一个数量,对多个进程可见.多个进程可以通过方
法操作这个数量,达到协同工作的目的
from multiprocessing import Semaphore
1.sem = Semaphore(num)
功能: 创建信号量
参数: 初始化信号量
返回值 : 信号量对象
2.sem.acquire()
功能 : 将消耗一个信号量,当信号量为0会阻塞
3.sem.release()
功能 : 增加一个信号量资源
4.sem.get_value()
功能 : 获取信号量资源数量
1. 多任务编程之 线程 (Thread)
多任务编程之 线程 (Thread)
1.什么是线程?
1. 线程也是多任务编程方法
2. 线程也可以使用计算机多核资源
3. 线程被称为轻量级的进程,也是运行状态的概念
4. 一个进程中可以包含多个线程,线程是进程的一部分
5. 线程是系统分配内核的最小单位
2.线程特征
1. 线程也是运行状态,有生命周期,消耗计算机资源
2. 多个线程之间独立运行互不干扰
3. 一个进程内的线程共享进程资源
4. 线程的创建删除消耗的系统资源远远小于进程
5. 线程也有自己独立的资源,栈空间,命令集,ID等
1. threading 模块创建线程
threading 模块创建线程
from threading import Thread
1.t = Thread() #创建线程对象
功能 : 创建线程对象
参数 : target 绑定线程函数
args 元组 给线程函数传参
kwargs 字典 给线程函数传参
name 线程名 默认 Thread-1
2.t.start() #启动线程,自动运行线程函数
3.t.join([timeout]) #阻塞等待回收线程
2. 线程对象属性
线程对象属性:
1.t.name 线程名称
2.t.setName() 设置名称
3.t.getName() 获取名称
4.t.is_alive() 线程状态
5.threading.currentThread() 获取当前线程对象
6.t.daemon 默认为False此时主线程退出分支线程继续执行
如果设置为True则主线程退出分支线程也结束执行
7.t.setDaemon(True) 设置daemon属性
8.t.isDaemon() 查看daemon属性
* 在start前设置,通常不和join() 同用
3. 自定义线程类
自定义线程类
步骤:
1. 继承 Thread 类
2. 添加自己的属性__init__,加载父类__init__
3. 重写run
4. 使用自己的类生成线程对象.调用start()会自 动以一个线程执行run
4.线程的通信
线程的通信:
通信方法 :使用进程空间中的全局变量通信
注意事项 : 共享资源争夺,往往需要同步互斥机制协调
5. 线程同步互斥
线程同步互斥:
1.共享资源(临界资源): 多个线程都可以操作的资源称为共享资源
2.临界区 : 指一段代码,对临界资源操作的代码段
3.同步: 同步是一种合作关系,为完成任务,多个进程或者
线程之间形成一种协调调度,按照必要的步骤有
序执行一系列操作
4.互斥: 互斥是一种制约关系,当一个进程或者线程使用
临界资源时会进行加锁处理,此时另一个进程或
者线程就无法操作,直到解锁后才能操作
2. 线程同步互斥方法
线程同步互斥方法
1.线程 Event
from threading import Event
e = Event()
功能 : 创建事件对象 (事件对象初始为未设置状态)
e.wait([timeout])
功能 : 如果e是未设置的状态则阻塞
如果e 是被设置状态则不阻塞
参数 : timeout 超时时间
e.set() 将e变为被设置状态
e.clear() 清除e的设置
e.is_set() 判断当前e的状态 设置-->True
未设置--> False
2.线程锁 Lock
from threading import Lock
lock = Lock() 创建锁对象
lock.acquire() 上锁, 如果已经上锁调用该函数阻塞
lock.release() 解锁
with lock: 上锁
...
...
with代码段结束则解锁
3. python 线程的GIL问题 (全局解释器锁)
python 线程的GIL问题 (全局解释器锁):
1.GIL : 由于Python解释器中加入了全局解释器锁,导致
python解释器同一时刻只能解释一个线程,所以大大
降低了Python多线程的执行效率.
2.后果 : Python线程一般只能用在大量IO阻塞存在,或则高延
迟的IO程序中.遇到阻塞,线程会自动让出解释器.而
在cpu密集型程序中,Python线程效率低下
3.GIL问题建议:
* 尽量使用多进程完成并发
* 不使用c作为解释器情况没有GIL问题 java c#
* 使用多种阻塞方案完成并发
测试:
Line cpu: 8.797621726989746
Line IO: 5.032757759094238
Thread cpu: 8.930429458618164
Thread IO: 5.855912685394287
Process cpu: 4.457605838775635
Process io: 3.3356571197509766
作业 :
1. 多进程和多线程的编程特点及区别
2. 复习网络套接字使用
3. 编码思路流程
前情回顾
1. 进程间通信
共享内存 : 在内存中开辟区域,效率较高
Value() --> 单一数据
Array() --> 数据结构
信号量 : Semaphore() 创建信号量
acquire() 消耗
release() 增加
get_value() 获取个数
2. 多线程
threading --> Thread() 创建线程
start() 启动线程
join() 回收线程
线程对象属性
t.name
t.daemon
t.is_alive()
3. 创建自定义线程类
1. 继承Thread
2. 编写自己的属性 __init__
3. 重写run方法
线程通信 : 使用全局变量
同步互斥方法
Event()
set() clear() wait() is_set()
Lock()
acquire() release()
4. 线程的GIL问题: 全局解释器锁---> Python线程效率低
Day08
1. 进程和线程的区别和联系
进程和线程的区别和联系:
1. 两者都是多任务编程方式,都能够使用计算机内核,都是动态运行的过程,占有计算机资源
2. 进程的创建删除消耗资源要高于线程
3. 一个进程可以包含多个线程
4. 进程空间独立,数据互不干扰,有专门的IPC.线程使用全局变量通信
5. 多个线程共享进程的全局资源,资源操作时往往需要同步互斥方法
6. 进程线程在系统中都有特有属性,如ID代码段命令集等
2. 使用场景
使用场景:
* 一个任务包含多个分支任务,且需要消耗资源少时用线程
* 不同的独立任务,需要空间独立(方便资源的使用管理)用多进程
* IO多时,可能选择 进程 + IO多路复用.或者看通信中编码逻辑复杂程度
要求 :
1. 进程线程区别有哪些
2. 你在什么情况下使用线程或者进程
3. 什么是同步互斥,你在什么情况下使用,如何使用
4. 进程间的通信方法知道哪些,有什么特点
5. 你是如何处理僵尸进程的.
6. 进程池原理是什么,怎么用.
3. 网络通信模型
网络通信模型:
什么是服务器?
硬件服务器 : 主机 集群
软件服务器 : 编写的后端服务程序,在硬件服务器系统上运行,提供一定的后端服务
httpserver --> 处理http请求
webserver --> 处理网站后端服务
邮箱服务器 --> 邮件收发
文件服务器 --> 文件下载上传
架构模型 : C/S 客户端服务器模型
B/S 浏览器服务器模型
4.网络通信模型
网络通信模型
1.循环模型 : 循环接收客户端请求,处理请求.同一时刻只
处理一个请求,处理完毕后再处理下一个.
优点: 实现简单,占用资源少
缺点: 无法同时处理多个客户端请求
适用情况 : 处理任务可以很快完成的情况,不需要
建立并发,UDP比tcp更适合循环
2.IO并发模型: IO多路复用 协程
优点 : 能同时处理多个IO,资源消耗少
缺点 : 只能监控IO事件,当多任务是cpu运算时无法同时处理
3.多进程/线程并发模型 : 每当有一个客户端连接则创建一个新的进程或者线程处 理客户端请求
优点: 每个客户端可以长期占有服务器,使用多核进行IO处理或者cpu运算
缺点: 资源消耗较多
5. 多进程并发
多进程并发:
基于 fork 完成多进程并发
1. 创建套接字,绑定,监听
2. 等待接收客户端请求 accept
3. 当新的客户端连接后,创建新的进程处理客户端请求
4. 原有进程继续等待其他客户端连接
5. 如果客户端退出,则销毁对应进程
6. ftp文件服务器
ftp文件服务器
1.功能 : 1. 服务器分为客户端和服务端两部分,要求启动服务端可以同时有多个客户单操作
2. 客户端可以查看服务器文件库中的文件(客户端只能查看普通文件,不包含隐藏文件)
3. 客户端可以选择文件库中的文件进行下载
4. 客户端也可以上传本地文件到文件库
5. 使用print打印移动的命令提示界面
2.技术分析 : fork并发 tcp套接字
判断普通文件: os.path.isfile()
查看文件列表: os.listdir()
3.结构设计 : 将 2, 3, 4三个功能封装在一个类中
4.工作步骤 : 1. 搭建网络
2. 封装类
3. 功能函数实现并测试
5.网络tcp并发
服务端 : fork tcp并发服务器模型
客户端 : 连接服务端
作业 : 1. 总结ftp server
2. 复习 http协议, httpserver工作原理
前倾回顾
1. 进程和线程的区别联系
2. 服务器通信模型
循环模型 : 循环接收请求,每次处理一个
IO并发模型: 可以同时处理多个IO请求
多进程/线程并发: 针对每个客户端单独创建进程/线程
3. 基于fork的多进程并发
ftp文件服务器
Day09
1. 基于threading的多线程并发
基于threading的多线程并发:
步骤:
1. 创建套接字,绑定,监听
2. 接收客户端连接
3. 创建新的线程处理客户单请求
4. 主线程继续等待其他客户端连接
5. 当客户端退出时处理对应线程
2. 集成模块完成多进程/线程socket并发
1.集成模块完成多进程/线程socket并发:
python2 SocketServer
python3 socketserver
功能 : 通过模块提供的不同类的组合完成多进程或者多线程的tcp/udp并发程序
StreamRequestHandler 处理tcp请求
DatagramRequestHandler 处理udp请求
TCPServer 创建tcpserver
UDPServer 创建udpserver
ForkingMixIn 创建多进程
ForkingTCPServer ForkingMixIn + TCPServer
ForkingUDPServer ForkingMixIn + UDPServer
ThreadingMixIn 创建多线程
ThreadingTCPServer ThreadingMixIn + TCPServer
ThreadingUDPServer ThreadingMixIn + UDPServer
使用步骤:
1. 创建服务器类,通过选择继承模块中的TCPServer或者UDPServer
确定服务器类型,继承多进程或者多线程类确定并发类型
2. 创建请求处理类,根据服务器类型选择继承流式套接字处理还是数据报套接字处理
3. 通过服务器类创建服务器对象,并绑定处理类.
4. 通过服务器对象调用 serve_forever()启动服务
5. 当客户端发起请求后,会自动调用请求处理类中handle()方法处理
3. HTTPServer V2.0
HTTPServer V2.0
功能 : 1. 接收客户端请求
2. 解析客户端请求
3. 组织数据,形成http响应格式
4. 将响应内容回发给客户端
升级:
1. 基本的请求解析,根据具体请求返回具体内容
2. 采用多线程并发,可以满足多个客户端的同时访问
3. 除了网页也可以获取一些简单数据
4. 使用类进行httpserver封装
技术点 :
* 使用 tcp套接字 socket多线程并发
* 类的封装 : 使用类实例化对象,对象调用启动接口
* http请求和响应格式
请求:
请求行 GET /abc.html HTTP/1.1
请求头
空行
请求体
响应:
响应行 HTTP/1.1 200 OK
响应头
空行
响应体 具体内容
4. 协程
协程:
1.定义 : 纤程,微线程.是为非抢占式多任务产生子程序的计算机程序组件.
协程允许不同入口点,在不同位置暂停或者开始执行,简单来说,协
程就是可以暂停执行的函数
* yield 是实现协程的基本关键字
2.协程原理: 记录一个函数栈的上下文,进行协程的切换调度当一个协程函数暂
停执行时会将上下文栈帧保存起开,在切换回来时恢复到原来的执
行位置,从而继续执行
3.协程优点:
1. 协程可以同时处理多个任务
2. 协程本质是单线程,资源消耗少
3. 协程无需切换的开销,无需同步互斥
4.协程缺点:
1. 无法利用计算机多核
5.greenlet
安装: sudo pip3 install greenlet
1.g = greenlet.greenlet(func)
功能 : 创建协程对象
参数 : 协程函数
2.g.switch()
功能 : 启动协程函数
6.gevent
安装: sudo pip3 install gevent
1.gevent.spawn(func,argv)
功能 : 生成协程对象
参数 : func 协程函数
argv 给协程函数传参
返回值 : 返回协程对象
* 当func函数中遇到gevent类型阻塞则会跳出
2.gevent.joinall(list,[timeout])
功能 : 阻塞等待回收协程
参数 : list 协程对象列表
timeout 超时时间
3.gevent.sleep(sec):
功能: 提供协程阻塞
from gevent import monkey
4.monkey.patch_all()
功能: 修改原有的IO阻塞行为,可以出发协程事件跳转
* 必须在模块导入前设置
作业 : 1. 总结进程线程网络内容知识点
2. 复习 pymysql 使用
3. 看 ftp 和 聊天室 思维流程
4. httpserver 第二版
前情回顾
1. 多线程并发模型
2. socketserver模块
3. HTTPServer第二版
4. 协程
什么是协程? 本质就是可以暂停执行的函数
greenlet
greenlet() switch()
gevent
spawn() joinall() sleep() monkey
Day10-项目
1. 项目练习 - 电子词典
项目练习 - 电子词典
功能说明 :
1. 用户可以登录和注册
登录凭借用户名密码即可
注册要求用户必须填写用户名密码,其他内容自定
用户名不能重复,且用户数据可以长期保存
2. 服务端和客户端,要求可以满足多个客户端同时登陆
3. 客户端 启动后即进入一级界面,功能如下
注册 登陆 退出
* 如果注册或者登陆失败,返回一级界面
4. 如果用户登录成功即可进入二级界面,功能如下
查词 查看历史记录 注销
查词 : 可以循环查词,输入单词,得到单词解释
输入##退出查词
单词本 : 每行一个单词
单词按从小到大排列
单词和解释之间有空格
历史记录: 选择该项即可显示当前登录用户最近的查词
记录.(可以显示左右,也可以显示最近10条)
格式: name word time
注销 : 回到一级界面
1. 确定技术点
数据库使用 : mysql
确定单词查询方法 : 文本数据库?
文本 数据库
确定套接字和并发方法 : 什么套接字,什么并发?
tcp 多进程
2. 建立数据库和数据表
确定几个表,表的关系,表的字段,字段类型
create database dict default charset=utf8;
用户 : id name passwd
create table user (id int primary key auto_increment,name varchar(32) not null,passwd varchar(16) default '000000');
历史记录: id name word time
create table hist (id int primary key auto_increment,name varchar(32) not null,word varchar(128) not null,time varchar(128));
单词表 : id word interpret
create table words (id int primary key auto_increment,word varchar(128),interpret text);
如果使用数据库查词,将单词插入数据库
3. 项目结构分析,分为几部分,几个功能模块
服务端 创建套接字 --> 创建父子进程 -->子进程循环接收客户端请求-->父进程继续等待其他 客户端连接
请求类型 : 注册,登录,查询,历史记录,退出
客户端 创建套接字 --> 发起连接请求 --> 进入一级界面 --> 循环发送请求 --> 登录以后 循环发送请求
4. 搭建通信模型
5. 具体功能实现
注册
客户端 : 1. 输入注册信息
2. 将信息发送给服务器
3. 等待得到服务器反馈
服务端 : 1. 接收请求
2. 判断是否允许注册
3. 将结果反馈给用户
4. 将注册信息插入数据库
登录
客户端 : 1. 输入用户名密码
2. 将请求发送给服务端
3. 得到服务端反馈
4. 进入二级界面
服务端 : 1. 接收请求
2. 验证是否允许登录
3. 反馈结果
查词
客户端 : 1. 发送请求 Q name word
2. 得到反馈结果
3. ##退出
服务端 : 1. 接收请求
2. 查找单词
3. 反馈结果
4. 插入历史记录
历史记录
cookie
import getpass
getpass.getpass()
功能: 隐藏密码输入
作业 : 1. 梳理电子词典代码
2. 对进程线程网络总结
4、Regex-正则表达式
Day01-正则表达式
1、正则表达式概念
动机
1. 文本处理已经成为计算机的常见工作之一
2. 对文本内容的搜索,定位,提取是逻辑比较复杂的工作
3. 为了快速方便的解决上述问题,产生了正则表达式
定义: 即文本的高级匹配模式,提供搜索替换等功能.其本质
是一系列由字符和特殊符号组成的字符串,这个字符串
即正则表达式
匹配原理 : 由普通的字符和特殊符号构成,通过描述字符的
重复,位置,种类等行为达到匹配某一类字符串的
目的
正则特点 :
* 方便处理文本
* 支持语言众多
* 使用灵活多样
目标 : 1. 熟练掌握正则表达式符号
2. 读懂正则表达式,编写简单的正则表达式
3. 能够使用Python re操作正则表达式
2、Python --> re模块
re.findall(pattern,string)
功能: 使用正则表达式匹配字符串
参数: pattern 正则表达式
string 目标字符串
返回值 : 返回匹配内容列表
3、元字符的使用
1. 普通字符
元字符 : a B c
匹配规则: 每个字符匹配对应的自身字符
In [15]: re.findall('ab','abcdaefabcdef')
Out[15]: ['ab', 'ab']
In [16]: re.findall('你好','你好,北京')
Out[16]: ['你好']
2. 或
元字符 : |
匹配规则: 匹配 | 两边任意一个正则表达式
In [24]: re.findall('ab|cd',"abcdef")
Out[24]: ['ab', 'cd']
3. 匹配单个字符
元字符 : .
匹配规则: 匹配除换行外任意一个字符
f.o --> foo fao
In [25]: re.findall('f.o',"foo fao")
Out[25]: ['foo', 'fao']
4. 匹配字符串开始位置
元字符 : ^
匹配规则: 匹配目标字符串的开始位置
In [29]: re.findall('^Jame',"Jame is a boy")
Out[29]: ['Jame']
5. 匹配字符串结束位置
元字符 : $
匹配规则: 匹配目标字符串的结束位置
In [32]: re.findall('Jame$',"Hi,Jame")
Out[32]: ['Jame']
6. 匹配重复
元字符 : *
匹配规则: 匹配前面的字符出现0次或多次
fo* --> fooooooooooo f
In [34]: re.findall('fo*',"fooooooabceffo")
Out[34]: ['foooooo', 'f', 'fo']
7. 匹配重复
元字符: +
匹配规则 : 匹配前面的字符出现1次或多次
fo+ --> fooooooooooo fo
In [37]: re.findall('fo+',"fooooooabceffo")
Out[37]: ['foooooo', 'fo']
8. 匹配重复
元字符 : ?
匹配规则 : 匹配前面的字符出现0次或1次
fo? --> f fo
In [43]: re.findall('fo?',"fooooooabceffo")
Out[43]: ['fo', 'f', 'fo']
9. 匹配重复
元字符 : {n}
匹配规则 : 匹配前面的字符重复指定的次数
fo{3} --> fooo
In [46]: re.findall('fo{3}',"fooooooabceffo")
Out[46]: ['fooo']
10. 匹配重复
元字符 : {m,n}
匹配规则 : 匹配前面的字符出现 m -- n次
fo{2,4} --> foo fooo foooo
In [49]: re.findall('fo{2,4}',"fooooooabceffoo")
Out[49]: ['foooo', 'foo']
11. 匹配字符集
元字符: [字符集]
匹配规则: 匹配字符集中任意一个字符
[abc123] --> a b c 1 2 3
[a-z] [A-Z] [0-9]
[$#_a-zA-Z]
In [50]: re.findall('[A-Z][a-z]*',"Hi,This is Lua")
Out[50]: ['Hi', 'This', 'Lua']
12. 匹配字符集
元字符 : [^...]
匹配规则 : 匹配除指定字符外的任意一个字符
[^abc] --> 除了a b c外任意一个字符
[^a-z]
In [61]: re.findall('[^ ]+',"This is a test")
Out[61]: ['This', 'is', 'a', 'test']
13. 匹配任意(非)数字字符
元字符 : \d \D
匹配规则: \d 匹配任意一个数字字符 [0-9]
\D 匹配任意一个非数字字符 [^0-9]
In [63]: re.findall('\d+',"2018年就快过去,2019马上到来")
Out[63]: ['2018', '2019']
14. 匹配任意(非)普通字符
元字符 : \w \W
匹配规则: \w 匹配普通字符 (数字字母下划线,utf8字符)
\W 匹配特殊字符
In [71]: re.findall('\w+',"PORT#1234,Error 44% 下降")
Out[71]: ['PORT', '1234', 'Error', '44', '下降']
15. 匹配任意(非)空字符
元字符 : \s \S
匹配规则: \s 匹配任意空字符 [ \r\n\t\v\f]
\S 匹配任意非空字符
In [72]: re.findall('\w+\s+\w+',"hello world")
Out[72]: ['hello world']
In [74]: re.findall('^\S+',"Terna-123#H xxxxxxx")
Out[74]: ['Terna-123#H']
16. 匹配字符串开头结尾位置
元字符 : \A \Z
匹配规则: \A 匹配字符串开头位置
\Z 匹配字符串结尾位置
In [80]: re.findall('\A\d+-\d+\Z',"1000-15000")
Out[80]: ['1000-15000']
绝对匹配(完全匹配) : 保证正则表达式匹配目标字符串的全部内容
17. 匹配(非)单词边界
元字符 : \b \B
匹配规则: \b 匹配单词边界 (普通字符和其他字符的交接)
\B 匹配非单词边界
In [85]: re.findall(r'\bis\b',"This is a boy")
Out[85]: ['is']
In [86]: re.findall(r'\Bis',"This is a boy")
Out[86]: ['is']
元字符总结
#元字符总结:
匹配单个字符: . [...] [^...] \d \D \w \W \s \S
匹配重复: * + ? {n} {m,n}
匹配位置: ^ $ \A \Z \b \B
其他: | () \
4、正则表达式的转义
#正则表达式的转义:
正则特殊符号: . * + ? ^ $ () [] | \
正则表达式如果匹配特殊字本身符则需要加\
e.g. 匹配字符 . 用 \.
目标字符串 正则表达式 字符串
$10 \$\d+ "\\$\\d+"
raw字串: 对字符串不进行转义解析
r'\$\d+' ==> '\\$\\d+'
5、贪婪和非贪婪
#贪婪和非贪婪
1.贪婪模式: 正则表达式的重复匹配默认总是尽可能多的向后匹配内容
* + ? {m,n}
2.非贪婪(懒惰)模式 : 尽可能少的匹配内容
贪婪-->非贪婪 *? +? ?? {m,n}?
In [105]: re.findall(r'ab+?',"abbbbbbbbb")
Out[105]: ['ab']
6、正则表达式分组
#正则表达式分组:
1.使用 () 可以为正则表达式内部建立分组. 通过分组构建正则表达式的内部整体处理部分
* 子组是正则表达式的一部分,子组需要再整体能够匹配内容的前提下发挥作用
2.子组的作用:
1. 作为一个内部整体,改变某些元字符的操作对象
re.search(r'\w+@\w+\.(com|cn)','abc@123.cn').group()
Out[113]: 'abc@123.cn'
2. 在匹配到内容的前提下,子组对应内容可以单独提取
re.search(r'(http|https|ftp)://\S+','https://www.baidu.com').group(1)
Out[116]: 'https'
7、捕获组和非捕获组
#捕获组和非捕获组
捕获组 : 被命名的子组
格式 : (?P<name>pattern)
作用 : 名字可以表达一定的含义,也可以通过名字来 提取子组对应内容
re.search(r'(?P<big>[A-Z])\w*','Hello world').group('big')
Out[119]: 'H'
* 一个正则表达式中可以有多个子组.多个子组尽量不要重叠或者过多嵌套.通常由外到内,从左到右分为第一第二子组
8、正则表达式的设计原则:
1. 正确性 : 能够正确的匹配目标字符串
2. 排他性 : 除了要匹配的内容,尽可能不会匹配到其他多余内容
3. 全面性 : 尽可能将目标字符串的全部情况考虑全面,不遗漏
9、re模块
1.regex = compile(pattern,flags = 0)
功能: 生成正则表达式对象
参数: pattern 正则表达式
flags 功能标识,用来丰富正则表达式功能
返回值 : 正则表达式对象
2.re.findall(pattern,string,flags)
功能: 使用正则表达式匹配目标字符串
参数: pattern 正则表达式
string 目标字符串
flags 标志位
返回值: 列表, 匹配到的内容
如果正则表达式有子组则只获取子组对应内容
3.regex.findall(string,pos,endpos)
功能: 使用正则表达式匹配目标字符串
参数: string 目标字符串
pos 匹配目标的起始位置
endpos 匹配目标的结束位置
返回值: 列表, 匹配到的内容
如果正则表达式有子组则只获取子组对应内容
4.re.split(pattern,string,flags)
功能 : 使用正则匹配到的部分切割目标字符串
参数 : pattern 正则
string 目标字串
flags 标志位
返回值 : 返回列表,为切割后内容
5.re.sub(pattern,replaceStr,string,max,flags)
功能: 使用字符串替换匹配到的内容
参数: replaceStr 替换字串
max 最多替换基础 默认全部替换
返回值 : 返回替换后的字符串
6.re.subn(pattern,replaceStr,string,max,flags)
功能参数同sub
返回值 : 返回替换后的字符串和替换数量
7.re.finditer(pattern,string,flags)
功能 : 使用正则表达式匹配目标字符串
参数 : pattern 正则
string 目标字串
flags 标志位
返回值 : 返回一个包含匹配内容的迭代对象
8.re.fullmatch(pattern,string,flags)
功能 : 完全匹配一个目标字符串
参数 : pattern 正则
string 目标字串
flags 标志位
返回值 : match对象
9.re.match(pattern,string,flags)
功能 : 匹配一个目标字符串开始位置
参数 : pattern 正则
string 目标字串
flags 标志位
返回值 : match对象
10.search(pattern,string,flags)
功能 : 匹配目标字符串第一处匹配内容
参数 : pattern 正则
string 目标字串
flags 标志位
返回值 : match对象
compile对象属性变量:
pattern : 正则表达式
flags : 标志位值
groupindex : 获取捕获组名和对应序列号的字典
groups: 子组数量
match对象的属性和函数:
属性
pos #目标子串开始位置
endpos #目标子串结束位置
re #正则表达式
string #目标字符串
lastgroup #最后一组组名
lastindex #最后一组序列号
方法
start() #匹配内容的开始位置
end() #匹配内容的结束位置
span() #匹配内容的起止位置
group(n)
功能 : 获取match对象的对应内容
参数 : 默认为0表示获取match对象所有对应内容
如果为>0整数则表示某个子组对应内容
如果为子组名称则表示对应捕获组匹配内容
返回值: 返回对应字符串
groupdict()
功能: 获取捕获组和对应值的字典
groups()
功能: 获取所有子组对应内容
作业: 使用re模块 函数 用 compile 在写一遍
熟记元字符
编写一个程序,匹配一个文档中
1. 所有大写字母开头单词
2. 所有数字,数字包括
整数 小数 分数 百分数 负数
123 1.24 1/2 45% -2.5
5、MySQL-数据库
Day01笔记-库-表(管理)
1. MySQL概述
1. MySQL概述
1. 什么是数据库
数据库就是存储数据的仓库
2. 都有哪些公司在使用数据库?
电商公司,游戏公司,金融机构,政府部门...
3. 提供数据库服务的软件
1. 软件分类
MySQL,Oracle,SQL-Server,DB2,MongoDB,MariaDB...
2. 生产环境中,如何选择使用哪一种数据库软件
1. 是否开源
1. 开源软件 : MySQL,MongoDB,MariaDB
2. 商业软件 : Oracle,DB2,SQL-Server
2. 是否跨平台
1. 不跨平台 : SQL-Server
2. 跨平台 : ...
3. 公司类型
1. 商业软件 : 政府机构,金融机构
2. 开源软件 : 游戏公司,电商公司,论坛和贴吧网站...
4. MySQL 数据库特点:
1. 关系型数据库
1. 关系型数据库的特点
1. 数据以行和列(表格)形式存储
2. 表中每一行叫一条记录,每一列叫一个字段
3. 表与表之间的逻辑关联叫关系
2. 实例
1. 关系型数据库存储数据:
表1 学生信息表
姓名 年龄 班级
星矢 25 三班
水冰月 25 六班
表2 班级信息表
班级 班主任
三班 大空翼
六班 松人
2. 非关系型数据库存储数据
{"姓名":"星矢","年龄":"25","班级":"三班","班主任":"大空翼"}
{"姓名":"水冰月","年龄":"25","班级":"六班","班主任":"松人"}
2. 跨平台
可以在Windows,Linus,Unix上运行
3. 支持多种编程语言
Python,Java,PHP...
5. 数据库软件,数据库,数据仓库的概念
1. 数据库(database 简写DB,db)
储存在计算机内的有组织,可共享的数据集合
2. 数据库软件(数据库管理系统)
一个软件,看得见,可操作的工具,可以通过SQL语句操作数据库(SQL: 结构化查询语句)
3. 数据仓库(Data WareHouse,简写 DW,DWH)
数据量要比数据库大的多,主要用于数据分析和数据挖掘
et :
数据库 : 购物车表,用户信息表
数据仓库 : 分析哪个时间段用户的访问量最大,哪个用户一年中购物最多....
2. MySQL安装
2. MySQL安装
1. Ubuntu安装MySQL服务(命令行安装)
1. 安装服务端
sudo apt-get install mysql-server
2. 安装客户端
sudo apt-get install mysql-client
3. Ubuntu安装软件
1. sudo apt-get update
访问源列表中的每个网址,读取软件列表,保存到本地/var/lib/apt/lists
2. sudo apt-get upgrade
把本地已安装软件与刚下载的软件列表进行比对,如果发现已安装软件的版本低,则更新软件
3. sudo apt-get -f install
修复依赖关系
2. Windows安装MySQL
1. 下载安装包
mysql-installer***5.7.24.msi
2. 按照安装教程安装
3. Mac 安装MySQL
1. 下载安装包 (dmg -> pkg)
2. 设置环境变量
1. vi .base_profile
2. 在末尾写入如下内容,保存并退出
export PATH=${PATH}:/usr/local/mysql/bin
或者
PATH="$PATH":/usr/local/mysql/bin
3. 在命令行下 $ source .base_profile
4. 登录测试
mysql -uroot -p
3. 启动和连接数据库
3. 启动和连接数据库
1. 启动服务端(终端下)
1. 查看MySQL状态
sudo /etc/init.d/mysql status
启动MySQL服务
sudo /etc/init.d/mysql start | stop | restart
2. 客户端连接
1. 命令格式 :
mysql -h主机地址 -u用户名 -p密码
et :
mysql -hlocalhost -uroot -p123456
2. 本地连接可以省略-h选项
mysql -uroot -p123456
4. 基本SQL命令
1. SQL命令的使用规则
1. SQL命令的使用规则
1. SQL命令不区分大小写,但是区分中英文的标点符号,一律使用英文标点符号 "" : 空格
2. 每条命令以;结尾
3. 使用\c终止当前命令的执行
2. 库的管理
2. 库的管理
1. 库的基本操作
1. 查看已有库
show databases;
2. 创建库
create database 库名;
创建的同时指定字符集
create database 库名 character set utf8;
3. 查看创建库的语句(字符集)
show create database 库名;
4. 查看当前所在库
select database();
5. 切换/选择库
use 库名;
6. 查看当前库中所有的表
show tables;
7. 删除库
drop database 库名;
2. 库名的命名规则
1. 库名由数字,字母,下划线组成,不能使用纯数字
2. 库名区分大小写
et :
1. SQL命令不区分大小写
CREATE DATABASE TESTDB;
等价于
create database TESTDB;
2. 库名区分大小写
create database TESTDB;
create database Testdb;
分别创建了两个库 :
TESTDB
Testdb
3. 不能使用特殊字符和MySQL的关键字
练习 :
1. 创建库studb,指定字符集为utf8
create database studb character set utf8;
2. 进入studb库中
use studb;
3. 查看当前所在库
select database();
4. 创建库studb2,指定字符集为latin1
create database studb2 character set latin1;
5. 进入studb2中
use studb2;
6. 查看当前库的字符集
show create database studb2;
7. 删除创建好的两个库
drop database studb;
drop database studb2;
3. 表记录管理
3. 表记录管理
1. 表的管理
1. 表的基本操作
1. 创建表
create table 表名(字段名 数据类型,字段2 数据类型,...);
创建的同时制定字符集
create table 表名(字段1 数据类型,字段2 数据类型,...)character set utf8;
2. 查看已有表的字符集
show create table 表名;
3. 查看表结构
desc 表名;
4. 删除表
drop table 表名;
练习 :
1. 创建库 studb
2. 在库中创建stuinfo表,指定字符集为utf8,指定字段 id name age;
3. 查看创建表stuinfo的语句
4. 查看表结构
5. 在库中创建score表,字段有id name score;
6. 查看库中所有表;
show tables;
7. 查看score表结构
8. 删除表,删除库
注意 :
1. 如果涉及多个库切换操作表,一定不要忘了切换数据库
2. 所有的数据在数据库中都是以文件的形式存储的,存放目录为:
/var/lib/mysql
2. 表记录管理(操作数据)
1. 插入数据 (insert)
1. insert into 表名 values(值1),(值2),...;
注意 : ()中实际代表的是一行,一条记录
insert into stuinfo values(1,'张三丰',300),(2,'张无忌',28);
2. insert into 表名(字段1,字段2,..) values(值1),(值2),..;
et :
insert into stuinfo(name,age) values('小昭',20),('敏敏',20);
2. 查询数据(select)
1. select * from 表名;
//查询表中所有数据
2. select * from 表名 where 条件;
//查询表中满足条件的数据
3. select 字段1,字段2 from 表名 [where 条件];
注意 : []表示可选添加
练习 :
1. 查看所有的库
show databases;
2. 创建新库 studb
create database studb character set utf8;
3. 在库中创建表tab1,指定字符集utf8,设置字段id name age
use studb;
create table tab1(id int,name char(10),age int)character set utf8;
4. 查看表结构
desc tab1;
5. 在tab1中插入两条记录
insert into tab1 values(1,'Jack',20),(2,'Rose',20);
6. 在tab1中name,age两个字段中插入两条记录
insert into tab1(name,age) values('Tom',100),('Jerry',100);
7. 查看表中所有记录
select * from tab1;
8. 查看表中年龄大于30的数据
select * from tab1 where age > 30;
4. 更改默认字符集
4. 更改默认字符集
1. 方法 : 修改mysql的配置文件
2. 步骤 :
1. 获取root权限
sudo -i
2. cd /etc/mysql/mysql.conf.d/
3. 备份(相当重要)
cp mysqld.cnf mysqld.cnf.bak
4. 修改
使用sublime修改 :
subl mysqld.cnf
找到 [mysqld]
添加 character_set_server = utf8
使用vi修改文件 :
vi mysqld.cnf
找到 [mysqld]
添加 character_set_server = utf8
5. 重启mysql服务
sudo /etc/init.d/mysql restart
6. 连接客户端
mysql -uroot -p123456
7. MAC 电脑
文件路径
/etc/my.cnf
[mysqld]
character_set_server = utf8
5. 数据类型
1. 数值类型
1. 数值类型
1. 整型
1. int 大整型(4个字节)
取值范围 : 0 ~ 2(32)-1
2. tinyint 微小整型(1个字节)
1. 有符号整型(默认)
取值范围 -128 ~ 127
id tinyint signed
2. 无符号整型(unsigned)
取值范围 0 ~ 255
age tinyint unsigned
3. smallint 小整型 (2字节)
4. bigint 极大整型 (8字节)
2. 浮点型
1. float(4个字节,最多显示7个有效位)
1. 用法
字段名 float(m,n)
m表示总位数,n表示小数位的位数
et :
score float(3,1)
2. double(8个字节)
float 是单精度 误差更大
double 是双精度 误差稍小,在mysql内部运算时,都采用double运算
3. decimal(最多可显示28个有效位)
用法 :
decimal(m,n)
m表示总位数,n表示小数位位数
3. 数值类型占用的存储空间
整数和小数分开存储的,需要各自计算所需的字节数
规则 :
将9的倍数包装成4个字节
余数占用字节对照表
余数 字节
0 0
1-2 1
3-4 2
5-6 3
7-8 4
et:
decimal(19,9)
计算存储空间 :
1. 整数位数 除以 9,
商表示占用4个字节,
余数,根据对照表判断占用几个字节
10 / 9 商 1 余数 1
占用字节数 4+1 = 5个字节
2. 小数位数 除以9
9 / 9 商 1 余数 0
占用字节数 4 + 0 = 4个字节
练习 :
1. 创建库studb2
create database studb2;
2. 在库中创建表stuinfo,要求 :
id 大整型
name 字符型,宽度是15
age 微小整型,不能为负数
height 浮点型,小数位为2位(float(5,2))
money 浮点型,小数位为2位(decimal(5,2))
et :
use studb2;
create table stuinfo(id int,name char(15),age tinyint unsigned,height float(5,2),money decimal(5,2));
3. 查看表结构
desc stuinfo;
4. 查看表的字符集
show create table stuinfo;
5. 插入1条完整记录,在表中id,name两个字段中插入两条记录
insert into stuinfo values(1, 'Jack',10,121.34,100.23);
insert into stuinfo(id,name) values(2,'Rose'),(3,'liming');
6. 查询所有记录
select * from stuinfo;
7. 查询所有学生的id和姓名
select id,name from stuinfo;
2. 字符类型
2. 字符类型
1. char(m)
m指定最大显示宽度,同时也指定最大字符个数
取值范围 1 ~ 255
特点 :
定长存储
char(10)
固定分配10个字符的空间存储数据
2. varchar(m)
m指定最大显示宽度,也制定最大字符个数
取值范围 : 1 ~ 65535
特点 :
变长存储
varchar(10)
根据数据的实际长度分配空间,小于10个字符,按照实际的字符数分配空间,
最大可分配10个字符的空间.
超过10个字符的数据,无法存储,会报错
3. text / longtext(4G) / blob / longblob(4G)
text相关的类型可用来存储大批量的文本数据(博文等)
blob相关的类型更适用于二进制数据的存储(图片)
注意 :
1. 定长和变长字符类型在存储空间上区别较大,
char 定长存储 : 浪费存储空间,但性能高
varchar 变长存储 : 节省存储空间,但性能低
2. 字符类型的显示宽度与数值类型宽度的区别 :
et : int(11)
char(10)
1. 数值类型的宽度为显示宽度,用于select查询是显示结果,和占用存储空间无关.
即使超出显示宽度,只要没有超出当前类型的取值范围,都可以插入成功
2. 字符类型的宽度不仅是显示宽度,还是最大字符个数,超出就无法存储
3. 数值类型如果指定显示宽度,而数据长度小于宽度,会自动补0,填充显示宽度.
结合zerofill 属性查看效果
id int(5) zerofill,
3. 枚举和集合
4.日期和时间类型
Day01 回顾
1. MySQL 特点:
1. 关系型数据库
2. 跨平台
3. 支持多种开发语言
4. 开源
2. 启动服务
sudo /etc/init.d/mysql start|restart|stop|status
mysql -h主机名 -u用户名 -p密码
本地连接可以省略-h
数据都是以文件形式存储在/var/lib/mysql
MySQL 核心是关系(二维表)
3. 基本SQL命令
show databases;
create database 库名 character set utf8;
use 库名;
create table 表名(字段1 数据类型,字段2 数据类型,...);
insert into 表名 values(记录1),(记录2),...;
insert into 表名(字段1,字段2,...) values(值1),()...;
select * from 表名;
select * from 表名 where 条件;
select 字段1,字段2 from 表名 where 条件;
show tables;
drop table 表名;
drop database 库名;
4. 更改默认字符集
1. sudo -i
2. cd /etc/mysql/mysql.conf.d
3. cp mysqld.cnf mysqld.cnf.bak
4. vi mysqld.cnf
[mysqld]
character_set_server = utf8
5. sudo /etc/init.d/mysql restart
6. mysql -uroot -p123456
5. 数据类型
1. 数值类型
1. 整型
1. int 大整型
2. tinyint 微小整型
1. 有符号 signed -128 ~ 127
2. 无符号 unsigned 0 ~ 255
3. smallint 小整形
4. bigint 极大整型
2. 浮点型
1. float(5,2)
2. decimal(5,2)
insert into info values("xiaoming",98),("xiaohong",96.12345);
注意 :
1. 浮点型,插入整数时,小数位会自动补0;
2. 小数位如果多于指定位,会自动对指定位的下一位四舍五入
2. 字符类型
1. char(定长) : 性能高,浪费空间
2. varchar(变长) : 性能低,节省空间
3. text / blob
注意 :
1. char(m),varchar(m)
m表示最大字符数,超出长度则无法存储
2. 区别 :
定长存储,会直接分配固定的存储空间 ;
变长存储,会根据实际的字符数,分配存储空间
3. 数值类型的显示宽度与字符类型的显示宽度 :
数值类型的显示宽度,不影响存储空间
字符类型的显示宽度,限制最大字符数,超出无法存储
Day02笔记
1. MySQL 数据类型
1. MySQL 数据类型
1. 数值类型
2. 字符类型
3. 枚举类型
1. 枚举 enum, 是一个字符串对象,可以将一些不重复的字符串存储成一个预定义的集合;字段值必须从这个集合中选取,才是合法值. 最多可以列举 65535 个值,
枚举经常用来实现单选 :
et :
create table userinfo(id int,name char(10),sex enum('男','女','保密'));
特点 :
枚举中的数据,从左到右会自动分配索引,从1开始,查询数据时,可以根据字符串值进行查询,也可以根据索引值查询
et :
select * from userinfo where sex='男';
等价于
select * from userinfo where sex=1;
2. 集合
集合是一种特殊的枚举类型,可以指定一个选项列表,但是字段值可以取范围内的多个值.可以实现多选.类型名使用set表示
et :
create table couseTab (sportcourse set('篮球','足球','羽毛球'));
insert into couseTab values('篮球,足球,羽毛球');
4. 日期时间类型
1. date : "YYYY-MM-DD"
2. time : "hh:mm:ss"
3. datetime : "YYYY-MM-DD hh:mm:ss"
4. timestamp : "YYYY-MM-DD hh:mm:ss"
注意 :
1. datetime : 给NULL,默认返回NULL
2. timestamp : 给NULL,默认返回系统当前时间
3. 日期格式 :
"2000/11/11 10:10:10"
"20081010121212"
5. 日期时间函数
1. now() 返回当前系统时间
2. curdate() 返回当前日期(年月日)
3. curtime() 返回当前时间(时分秒)
4. year(date) 返回指定日期的年份
5. date(date) 返回指定日期的年月日
6. time(date) 返回指定日期的时分秒
练习 :
1. 插入3条数据
2. 查找2018-10-10有哪些用户充值了?
select name from t1 where date(cztime) = "2018-10-10";
3. 查找2018年5月的充值信息
select * from t1 where date(cztime) >= "20180501" and date(cztime) <= "20180531";
4. 查找2018年8月30日10:00-12:00的充值信息
select * from t1 where date(cztime)="20180830" and time(cztime)>="100000" and time(cztime)<="120000";
6. 日期时间运算
1. 语法格式
select * from 表名 where 字段名 运算符 (时间-interval 时间单位)
时间单位 :
et :
1 day | 2 hour | 1 minute | 1 year | 1 month | 50 second
2. 练习 :
1. 查询1天以内的充值记录
select * from t1 where cztime > (now()-interval 1 day);
et :
age > 20
2. 查询1年前的充值记录
select * from t1 where cztime < (now()-interval 1 year);
3. 查询1天以前,3天以内的充值记录
select * from t1 where cztime < (now()-interval 1 day) and cztime > (now()-interval 3 day);
3. 表示未来的时间节点
et :
从当前系统时间向后推算一年,明年
now()-interval -1 year
2.表结构操作(操作字段)
2. 表结构操作(操作字段)
1. 语法 : alter table 表名 执行动作;
2. 添加字段 (add)
//直接在最后一列的位置添加新字段
alter table 表名 add 字段名 数据类型;
//在第一列的位置添加新字段
alter table 表名 add 字段名 数据类型 first;
//在指定字段的后面添加新字段
alter table 表名 add 字段名 数据类型 after 已有字段名;
3. 删除字段(drop)
alter table 表名 drop 字段名;
4. 修改数据类型(modify)
alter table 表名 modify 字段名 新数据类型;
5. 表的重命名(rename)
alter table 表名 rename 新表名;
练习 :
1. 创建库 studb;
create databse studb;
use studb;
2. 在库中创建表t1,字段 :
create table t1(name char(10),
age tinyint unsigned;
phnumber char(11));
3. 查看表结构
desc t1;
4. 在表中第一列的位置插入一个id字段
alter table t1 add id int first;
5. 修改phnumber的数据类型为int
alter table t1 modify phnumber int;
6. 在最后一列的位置插入address字段
alter table t1 add address char(20);
7. 删除age字段
alter table t1 drop age;
8. 查看表结构
desc t1;
id name phnumber address
9. 把表名修改为tab1;
alter table t1 rename tab1;
3. 表记录管理
3. 表记录管理
1. 插入数据 insert into 表名 values(),(),...;
2. 查询数据 select * from 表名 where 条件;
3. 删除数据
1. delete from 表名 where 条件;
2. 如果省略where条件,
delete from 表名;
表示清空所有记录
4. 更新数据
1. update 表名 set 字段1=值,字段2=值,... where 条件;
2. update 必须写where条件
练习 (hero):
1. 查找所有蜀国人的信息
select * from hero where country="蜀国";
2. 查找所有女英雄的姓名,性别,国家
select name,sex,country from hero where sex="女";
3. 把id=2的记录改为 典韦 性别 男,国家:魏国
update hero set name="典韦",sex="男",country="魏国" where id=2;
4. 删除所有蜀国英雄
delete from hero where country="蜀国";
5. 把貂蝉的国家改成魏国
update hero set country="魏国" where name="貂蝉";
6. 删除所有数据
delete from hero;
4. 运算符
4. 运算符
1. 数值比较/字符比较
1. 数值比较 : = != > >= < <=
2. 字符比较 : = !=
3. 练习 :
1. 查找攻击力超过150的英雄的名字和攻击值
select name,gongji from sanguo where gongji > 150;
2. 将赵云的攻击值设置为360,防御值设置为68
update sanguo set gongji=360,fangyu=68 where name='赵云';
2. 逻辑运算符
1. 条件1 and 条件2; (查询同时满足两个条件的数据)
2. 条件1 or 条件2;
查询满足条件1或者是满足条件2的数据
练习 :
1. 找出攻击值高于200的蜀国英雄的名字和攻击力
select name,gongji from sanguo where gongji > 200 and country = "蜀国";
2. 将吴国英雄攻击值为110的英雄,改为攻击力100,防御值60
update sanguo set gongji=100,fangyu=60 where country="吴国" and gongji=110;
3. 查找蜀国和魏国的英雄信息
select * from sanguo where country="蜀国" or country="魏国";
3. 范围内比较
1. between 值1 and 值2
设置范围在 值1 和 值2 之间
2. where 字段名 in(值1, 值2, 值3,...)
匹配字段值在 in 给出的范围内的数据
et :
where age in(22,23,24,25);
3. where 字段名 not in(值1,值2,..);
匹配字段值不在指定范围内的数据
练习 :
1. 查找攻击值在100-200之间的蜀国英雄信息
条件1 : 攻击值100-200
条件2 : 蜀国
select * from sanguo where
gongji between 100 and 200
and country="蜀国";
2. 查找蜀国和吴国以外的国家中,女英雄信息
条件1 : 国家不在蜀国和吴国中
条件2 : 女
select * from sanguo where
country not in('蜀国','吴国')
and sex="女";
3. 查找id=1,3,5的蜀国英雄和貂蝉的信息
条件1 : id= 1,3,5
条件2 : 蜀国
条件3 : name="貂蝉"
select * from sanguo where
id in(1,3,5) and country="蜀国"
or name="貂蝉";
4. 匹配空,非空
1. 匹配空 : where 字段 is null;
2. 匹配非空 : where 字段 is not null;
注意 :
1. is null 和 is not null 主要用来匹配字段值等于NULL的数据
2. 空字符串可以直接使用 = 来匹配
et :
where name='';
where name is null;
5. 模糊查询
1. 格式 : where 字段名 like 表达式
2. 表达式 :
1. _ : 表示匹配1个字符
2. % : 表示匹配0到多个字符
3. 示例:
1. 查找姓名包含2个字符(含)以上的数据
select * from sanguo where name like '_%_';
2. 匹配所有数据
select name from sanguo where name like "%";
注意 :
NULL值不会被匹配出来
空字符串表示0个字符,会被正常匹配
3. 匹配姓名为3个字符的数据
where name like '___';
4. 匹配姓赵的数据
where name like '赵%_';
et :
select name from sanguo where name like '赵%_';
更改查询结果中的显示字段
select name as n from sanguo where name like '赵%_';
5. SQL 查询
5. SQL 查询
1. 完整的查询语句由以下关键字组成
顺序为书写顺序,序号是mysql执行顺序
3. select
1. where
2. group by
4. having
5. order by
6. limit
2. order by : 对查询结果进行排序
1. 格式 : ...order by 字段名 ASC(升序)/DESC(降序)
2. 示例 :
1. 将英雄按照防御值从高到低排列
select * from sanguo order by fangyu DESC;
2. 将蜀国英雄按照攻击值从高到低降序排列
select * from sanguo where country="蜀国" order by gongji DESC;
3. 将魏国和蜀国英雄中名字为3个字的,按照防御值升序排列
select * from sanguo where country in ('魏国','蜀国') and name like "___" order by fangyu ASC;
3. limit 分页查询
永远放在SQL语句的最后书写
分页用来控制显示多少条结果中的数据
1. 语法 :
1. limit n; 表示显示n条数据
2. limit m,n; 表示从第m+1条记录开始显示,显示n条
et :
limit 2,3 : 显示第3,4,5 三条数据
3. 示例 :
1. 查找蜀国英雄中,防御值倒数第2名至倒数第四名的英雄记录
select * from sanguo where country="蜀国" order by fangyu ASC limit 1,3;
2. 查找蜀国英雄中攻击值前3名且名字不为NULL的英雄信息.
select * from sanguo where country="蜀国" and name is not null order by gongji DESC limit 3;
3. 显示查询结果中第20-25条数据
limit 19,6;
4. select 查询
select *
select 字段
select 聚合函数 where...
1. 聚合函数
最大值 最小值 求和 平均值 计数
Day02回顾
1.数据类型
1.数值类型
2.字符类型
3.枚举类型
1.字段名 enum(值1,值2)
2.字段名 set(值1,值2)
4.日期时间类型
1.date
2.time
3.datetime # 不给值默认NULL
4.timestamp # 不给值默认返回系统当前时间
2.日期时间函数
1.NOW()
2.CURDATE()
3.CURTIME()
4.YEAR(字段名)
5.DATE(字段名)
6.TIME(字段名)
3.日期时间运算
select ... from 表名
where 字段名 运算符(now()-interval 时间间隔单位);
1 day | 2 day | 3 month
4.表字段操作
1.添加(add)
alter table 表名 add 字段名 数据类型 first|after .
2.修改(modify)
alter table 表名 modify 字段名 新数据类型;
3.删除(drop)
alter table 表名 drop 字段名;
4.表重命名(rename)
alter table 表名 rename 新表名;
5.表字段重命名(change)
alter table 表名 change 原名 新名 数据类型;
5.表记录管理
1.删除(delete)
delete from 表名 where 条件;
2.修改(update)
update 表名 set 字段1=值1,字段2=值2 where 条件;
6.总结
表字段 表记录
增 add insert into 表名
删 drop delete from 表名
改 modify update 表名 set ...
查 desc select * from 表名 ...
7.运算符
1.数值&&字符&&逻辑比较
1.数值 : > >= < <= = !=
2.字符 : = !=
3.逻辑 : and or
2.范围内比较
1.between 值1 and 值2
2.in(值1,值2,值3)
3.not in(值1,值2,值3)
3.空 非空
1. is NULL
2. is not NULL
4.模糊比较
字段名 like "%_"
8.SQL查询
1.order by 字段名 ASC/DESC
2.limit
1. limit n
2. limit m,n
3. 分页
每页显示m条记录,显示第n页的内容
limit (n-1)*m,m
4.聚合函数
avg(..) sum(...) max(...) min(...)
count(...)
## 空值NULL不会被统计
Day03笔记
1. SQL查询
1. SQL查询
1.总结
3. select .... 聚合函数 from 表名
1. where ...
2. group by ...
4. having ...
5. order by ...
6. limit ...;
2. 聚合函数
1. 分类
avg(字段名)
sum(字段名)
max(字段名)
min(字段名)
count(字段名) : 统计该字段记录的个数
2.攻击力最大值是多少?
select max(gongji) from sanguo;
3.统计id name两个字段分别有几条记录?
select count(id),count(name) from sanguo;
# 空值NULL不会被统计,""会被统计
4.统计蜀国英雄中攻击力大于200的英雄的数量
select count(id) as number from sanguo where country="蜀国" and gongji>200;
3. group by : 给查询的结果进行分组
1. 示例
1. 计算每个国家的平均攻击力
select country,avg(gongji) from sanguo
group by country;
先分组 再聚合 最后去重
蜀国
蜀国
蜀国 578.25 蜀国
魏国
魏国 378.25 魏国
吴国 178.25 吴国
2. 查找所有国家的男英雄中,英雄数量最多的国家前2名,显示国家名称和英雄数量
1. 过滤男英雄
2. 每个国家有几个男英雄
3. 排序 + limit
3. select country,count(id) from sanguo
1. where sex="男"
2. group by country
4. order by count(id) desc
5. limit 2;
2. 注意
1.如果select后字段和group by之后不一致,则必须对该字段进行聚合处理(聚合函数)
4. having : 对分组聚合后的结果进行进一步筛选
1. 示例
找出平均攻击力大于105的国家的前2名,显示国家名称和平均攻击力
select country,avg(gongji) from sanguo
group by country
having avg(gongji)>105
order by avg(gongji) DESC
limit 2;
2. 注意
1. having语句通常与group by语句联合使用
2. having语句的存在弥补了where关键字不能与聚合函数联合使用的不足,where只能操作表中实际存在的字段
5. distinct : 不显示字段的重复值
1. 表中都有哪些国家
select distinct country from sanguo;
select distinct country,name from sanguo;
2. 注意
1. distinct和from之间所有字段都相同才会去重
2. distinct不能对任何字段做聚合处理
6. 查询表记录时可以做数学运算
1. 运算符 : + - * / %
2. 示例
查询时所有英雄攻击力翻倍
select name,gongji*2 as xgj from sanguo;
2.嵌套查询(子查询)
2. 嵌套查询(子查询)
1. 定义 : 把内层的查询结果作为外层的查询条件
2. 语法
select ... from 表名 where 字段名 运算符(查询);
select * from sanguo where id in(select ...)
select * from sanguo where (id,name) in();
3. 示例
1. 把攻击值小于平均攻击值的英雄名字和攻击值显示出来
select name,gongji from sanguo where gongji<(select avg(gongji) from sanguo);
2. 找出每个国家攻击力最高的英雄名字和攻击值
# 有BUG
select name,gongji from sanguo
where gongji in
(select max(gongji) from sanguo group by country);
# 完美
select name,gongji from sanguo
where (country,gongji) in
(select country,max(gongji) from sanguo group by country);
3. 多表查询
3. 多表查询
1. 两种方式
1. 笛卡尔积(不加where条件)
select 字段1,字段2 from 表1,表2;
2. 多表查询(加where条件)
... from 表1,表2 where 条件;
2. 示例
1. 显示省 市详细信息
select sheng.s_name,city.c_name from sheng,city where sheng.s_id=city.cfather_id;
2. 显示省 市 县详细信息
select sheng.s_name,city.c_name,xian.x_name from MOSHOU.sheng,MOSHOU.city,MOSHOU.xian
where sheng.s_id=city.cfather_id and city.c_id=xian.xfather_id;
4. 连接查询
4. 连接查询
1. 内连接(多表查询等价,只显示符合条件的记录)
1. 语法格式
select 字段名 from 表1 inner join 表2 on 条件
inner join 表3 on 条件;
2. 示例
1. 显示省 市详细信息
select sheng.s_name,city.c_name from MOSHOU.sheng inner join MOSHOU.city on MOSHOU.sheng.s_id=MOSHOU.city.cfather_id;
2. 显示省 市 县详细信息
select sheng.s_name,city.c_name,xian.x_name from sheng inner join city on sheng.s_id=city.cfather_id inner join xian on city.c_id=xian.XFATHER_ID;
2. 外连接
1. 左连接(left)
1. 定义 : 以左表为主显示查询结果
2. 示例
1. 显示省 市详细信息
2. 显示省 市 县详细信息,所有的市全都显示
select sheng.s_name,city.c_name,xian.x_name from
sheng right join city
on sheng.s_id=city.cfather_id
left join xian
on city.c_id=xian.xfather_id;
2. 右连接(right)
以右表为主显示查询结果,用法同左连接
5. 约束
5. 约束
1. 非空约束(not null)
2. 默认约束(default 默认值)
6. 索引(BTREE)
6. 索引(BTREE)
1. 定义
对数据库中表的一列或者多列的值进行排序的一种结构
2. 优点
加快数据的检索速度
3. 缺点
1. 占用物理存储空间
2. 当对表中数据更新时,索引需要动态维护,占用系统资源,降低数据的维护速度
4. 索引示例
1. 开启运行时间监测
mysql> set profiling=1;
2. 执行1条查询命令(没有创建索引)
select name from t1 where name="lucy88888";
3. 在name字段创建索引
create index name on t1(name);
4. 再执行1条查询命令
select name from t1 where name="lucy99999";
5. 对比执行时间
mysql> show profiles;
7. 索引分类
7. 索引分类
1. 普通索引(index) && 唯一索引(unique)
1. 使用规则
1.可设置多个字段
2.index无约束,unique字段值不能重复但可为NULL
3.把经常用来查询的字段设置为索引字段
4.index的KEY标志:MUL unique :UNI
2. 创建表时创建
create table 表名(
... ...
index(name),
index(id),
unique(phnumber),
unique(cardnumber)
);
3. 已有表中创建
create [unique] index 索引名 on 表名(字段名);
4. 查看索引
1. desc 表名; ——> KEY标志
2. show index from 表名;
5. 删除
drop index 索引名 on 表名;
Linux
在线:
sudo pip3 install pymysql
离线:
下载: XXX.tar.gz
解压: tar -zxvf XXX.tar.gz
cd XXX
sudo python3 setup.py install
Windows
cmd
python -m pip install pymysql
Day03回顾
1. SQL查询
1. 聚合函数
avg(...) sum(...) max(...) min(...)
count(字段名) ##空值NULL不会被统计
2. group by
1. select后的字段名如果没有在group by后出现,则必须对该字段进行聚合处理
3. having语句 : 对查询结果进一步筛选
where只能操作表中实际存在的字段,having可操作聚合函数生成的显示列
4. distinct
select distinct 字段1,字段2 from 表名;
5. 查询表记录时做数学运算
select 字段1*2 as name1,字段2+10 as name2 from 表;
2. 嵌套查询(子查询)
把内层的查询结果作为外层的查询条件
3. 多表查询
1. 笛卡尔积 : 不加where条件
2. 多表查询 : 加where条件,只显示匹配到的记录
4. 连接查询
1. 内连接 : 只显示匹配到的记录
2. 外连接
1.左连接 : 以左表为主显示查询结果
2.右连接 : 以右表为主显示查询结果
3. select 字段名 from 表1 inner/left/right join 表2 on 条件;
5. 约束
1. 非空约束(not null)
2. 默认约束(default 值)
6. 索引
1. 优点 : 加快数据的检索速度
2. 缺点
1. 占用物理存储空间
2. 需要动态维护,占用系统资源
3. SQL命令运行时间检测
1. 开启 : mysql> set profiling=1;
2. 查看 : mysql> show profiles;
3. 关闭 : mysql> set profiling=0;
7. 索引分类
1. 普通(MUL) 唯一(UNI,字段值不能重复,但是可为NULL)
2. 创建
index(字段名),index(字段名),
unique(字段名),unique(字段名)
create unique index 索引名 on 表名(字段名);
3. 查看
1. desc 表名; --> KEY标志
2. show index from 表名\G;
4. 删除
drop index 索引名 on 表名;(只能一个一个删)
Day04笔记
1. 主键(primary key) && 自增长属性(auto_increment)
1. 主键(primary key) && 自增长属性(auto_increment)
1. 使用规则
1. 只能有1个主键字段
2. 约束 : 不允许重复,且不能为NULL
3. KEY标志 : PRI
4. 通常设置记录编号的字段id,能唯一锁定1条记录
2. 创建表时
create table 表名(
id int primary key auto_increment,
... ...
)auto_increment=10000,charset=utf8,engine=InnoDB;
3. 已有表
alter table 表名 add primary key(id);
4. 删除
1. 删除自增长属性(modify)
alter table 表名 modify id int;
2. 删除主键(drop)
alter table 表名 drop primary key;
2. 外键(foreign key)
2. 外键(foreign key)
1. 定义 :让当前表字段的值在另一个表的范围内选择
2. 语法
foreign key(参考字段名)
references 主表(被参考字段名)
on delete 级联动作
on update 级联动作
3. 使用规则
1. 主表 从表字段数据类型要一致
2. 主表被参考字段 : 主键
4. 示例
表1 缴费信息表(财务)
id 姓名 班级 缴费金额
1 唐伯虎 AID09 300
2 点秋香 AID09 300
表2 学生信息表(班主任)
stu_id 姓名 缴费金额
1 唐伯虎 300
2 点秋香 300
XXXX 3 祝枝山 300 XXXX
表1 : jftab(主表)
create table jftab(
id int primary key,
name varchar(20),
class char(5),
money smallint
)charset=utf8;
insert into jftab values
(1,"唐伯虎","AID09",300),
(2,"点秋香","AID09",300),
(3,"祝枝山","AID09",300);
表2 : bjtab(从表)
create table bjtab(
stu_id int,
name varchar(20),
money smallint,
foreign key(stu_id) references jftab(id)
on delete cascade
on update cascade
)charset=utf8;
5. 删除
alter table 表名 drop foreign key 外键名;
外键名 : show create table 表名;
6. 已有表添加
alter table 表名 add
foreign key(..............
7. 级联动作
1. cascade
数据级联删除 更新(参考字段)
2. restrict(默认)
从表有相关联记录,不允许主表操作
3. set null
主表删除 更新,从表相关联记录字段值设置为NULL
3. 锁
3. 锁
1. 目的 : 解决客户端并发访问的冲突问题
2. 锁分类
1. 锁类型
1. 读锁(共享锁)
select : 加读锁之后别人不能更改表记录,但可以进行查询
2. 写锁(互斥锁 排他锁)
加写锁后别人不能查 不能改
2. 锁粒度
1. 表级锁 : 加读锁 写锁
2. 行级锁 : 加读锁 写锁
4. 存储引擎(处理表的处理器)
4. 存储引擎(处理表的处理器)
1. 基本操作
1. 查看所有存储引擎
mysql> show engines;
2. 查看已有表的存储引擎
mysql> show create table 表名;
3. 指定存储引擎
create table 表名(...)engine=MyISAM;
4. 已有表
alter table 表名 engine=InnoDB;
2. 常用存储引擎的特点
1. InnoDB
1. 支持外键 事务 事务回滚
2. 支持行级锁
3. 共享表空间
表名.frm : 表结构和索引文件
表名.ibd : 表记录
2. MyISAM
1. 支持表级锁
2. 独享表空间
表名.frm : 表结构
表名.MYD : 表记录(my data)
表名.MYI : 索引文件(my index)
3. MEMORY
表结构存储在硬盘中,表记录存储在内存中
服务/主机重启后,表结构还在,表记录消失
3. 如何决定使用哪个存储引擎
1. 执行查询操作多的表用MyISAM(使用InnoDB浪费资源)
2. 执行写操作多的表用InnoDB
5. 数据备份(mysqldump,在Linux终端中操作)
5. 数据备份(mysqldump,在Linux终端中操作)
1. 命令格式
mysqldump -u用户名 -p 源库名 > ~/XXX.sql
2. 源库名表示方式
--all-databases 备份所有库
库名 备份单个库
-B 库1 库2 库3 备份多个库
库名 表1 表2 表3 备份指定库的多张表
3. 练习
1. 备份所有库,all.sql
mysqldump -uroot -p --all-databases > all.sql
2. 备份MOSHOU库下的sheng city xian三张表
mysqldump -uroot -p MOSHOU sheng city xian > scx.sql
3. 备份 db4 库,db4.sql
mysqldump -uroot -p db4 > db4.sql
6. 数据恢复(Linux终端操作)
6. 数据恢复(Linux终端操作)
1. 命令格式
mysql -uroot -p 目标库名 < XXX.sql
mysql -uroot -p db4 < db4.sql
2. 从所有库备份中恢复某一个库(--one-database)
mysql -uroot -p --one-database 库名 < all.sql
3. 示例
1. 在MOSHOU.sheng新增1条记录
insert into sheng(s_id,s_name) values("300001","青海省");
2. 在MOSHOU新建1张表
create table t520(id int);
3. 恢复MOSHOU库
mysql -uroot -p --one-database MOSHOU < all.sql
4. 注意
1. 恢复库时,如果库不存在,则必须先创建空库
2. 恢复库时,恢复到原库会将表中数据覆盖,新增表不会删除
7. 数据导入
7. 数据导入
1. 作用 : 把文件系统的内容导入到数据库表中
2. 语法格式
load data infile "/var/lib/mysql-files/文件名"
into table 表名
fields terminated by "分隔符"
lines terminated by "\n"
3. 把scoreTable.csv文件导入到数据库表中
1. 在数据库创建对应的表
create table scoretab(
id int,
name varchar(20),
score float(5,2),
phnum char(11),
class char(7)
)charset=utf8;
2. 把文件拷贝到数据库的搜索路径中
1. 查看搜索路径
show variables like "secure_file_priv";
2. 拷贝
sudo cp scoreTable.csv /var/lib/mysql-files/
sudo -i
cd /var/lib/mysql-files/
chmod 644 scoreTable.csv
3. 执行数据导入语句
load data infile "/var/lib/mysql-files/scoreTable.csv"
into table scoretab
fields terminated by ","
lines terminated by "\n";
8. 数据导出
8. 数据导出
1. 作用 : 将数据库中表记录导出到系统文件里
2. 语法格式
select ... from 表名 where 条件
into outfile "/var/lib/mysql-files/文件名"
fields terminated by "分隔符"
lines terminated by "\n";
3. 示例
1. 把 sheng 表中所有记录导出来,sheng.csv
select * from MOSHOU.sheng
into outfile "/var/lib/mysql-files/sheng.csv"
fields terminated by ","
lines terminated by "\n";
2. 将 mysql 库下的user表中, user 和 host 两个字段的值导出来user.txt,以 " " 分隔
select user,host from mysql.user
into outfile "/var/lib/mysql-files/user.txt"
fields terminated by " "
lines terminated by "\n";
9. MySQL用户账户管理
9. MySQL用户账户管理
1. 开启MySQL远程连接
1. sudo -i
2. cd /etc/mysql/mysql.conf.d/
3. subl mysqld.cnf
#bind-address=127.0.0.1
4. /etc/init.d/mysql restart
2. 添加授权用户
1. 用root用户登录mysql
2. 授权
mysql> grant 权限列表 on 库.表
to "用户名"@"%" identified by "密码"
with grant option;
权限列表 : all privileges , select update
库.表 : *.* 库名.*
3. 示例
1. 添加用户tiger,密码123,对所有库的所有表有所有权限
grant all privileges on *.* to "tiger"@"%" identified by "123" with grant option;
2. 添加用户rabbit,密码123,对db4库有所有权限
grant select on db4.* to "rabbit"@"%" identified by "123" with grant option;
作业:
1. Homework.txt
2. 把/etc/passwd文件导入到数据库表中,userinfo
tarena : x : 1000 : 1000
用户名 密码 uid号 gid号
: tarena,,, : /home/tarena : /bin/bash
用户描述 主目录 登录权限
7列,6个:隔开
Day04回顾
1. 主键&&自增长(PRI,不能重复,不能为NULL)
1. 创建
id int primary key auto_increment,
alter table 表名 add primary key(字段名);
2. 删除
1. alter table 表名 modify id int;
2. alter table 表名 drop primary key;
3. 指定起始值
1. create table 表名(...)auto_increment=1000;
2. alter table 表名 auto_increment=1000;
2. 外键
1. 使用规则
1. 数据类型要一致
2. 主表被参考字段必须为KEY的一种 : PRI
2. 语法格式
constraint 外键名 foreign key(字段)
references 主表(字段)
on delete 级联动作
on update 级联动作
3. 级联动作
1. cascade : 删除 更新同步(被参考字段)
2. restrict(默认) : 不让主表删除 更新
3. set null : 删除 更新,从表该字段值设置为NULL
4. 删除
1. show create table 表名;
2. alter table 表名 drop foreign key 外键名;
3. 锁 : 解决客户端并发访问的冲突问题
1. 锁分类
1. 锁类型 : 读锁 写锁
2. 锁粒度 : 行级锁 表级锁
4. 存储引擎
mysql> show engines;
mysql> show create table 表名;
mysql> create table 表名(...)engine=MyISAM;
mysql> alter table 表名 engine=InnoDB;
5. 常用存储引擎
1. InnoDB : 支持外键 事务 行级锁 共享表空间
2. MyISAM : 支持表级锁,独享表空间
3. MEMORY : 表记录存储在内存中
4. 如何选择
查询操作多 : MyISAM
更新操作多 : InnoDB
6. 数据备份和恢复
1. 备份 : mysqldump -uroot -p 源库名 > XXX.sql
--all-databases
库名
-B 库1 库2 库3
库1 表1 表2 表3
2. 恢复 : mysql -uroot -p 目标库名 < XXX.sql
--one-database
1. 先创建空库再恢复
2. 库中新增表不会删除,新增记录会被覆盖
7. 用户授权
1. 开启远程连接
sudo -i
cd /etc/mysql/mysql.conf.d/
subl mysqld.cnf
# bind-address=127.0.0.1
/etc/init.d/mysql restart
2. 授权语句
mysql> grant all privileges on *.* to "lion"@"%" identified by "123456" with grant option;
8. 数据导入
1. 创建对应表
2. 拷贝文件
mysql> show variables like "secure_file_priv";
3. 执行导入语句
load data infile "/var/..."
into table 表名
fields terminated by ":"
lines terminated by "\n"
4. 修改权限
chmod 644 文件名
r : 4
w : 2
x : 1
9. 数据导出
select ... from 表名 where 条件
into outfile "/var/..."
fields terminated by ","
lines terminated by "\n"
Day05笔记
1. E-R模型(Entry-Relationship)
1. E-R模型(Entry-Relationship)
1. 定义 : 实体关系数据模型,用于数据库设计
2. 实体 : 描述客观事物的概念(1个人 1本书 1个学生)
1. 表示方法 : 矩形框
3. 属性 : 实体具有的某种特性
学生 : 学号 姓名 年龄 性别 专业 ... ...
表示方法 : 椭圆形
4. 关系 : 实体之间的关系
1. 一对一(1:1) : 老公对老婆
A中1个实体,B中只能有1个实体与其发生关联
B中1个实体,A中也只能有1个实体与其发生关联
2. 一对多(1:n) : 父亲对孩子
3. 多对多(m:n) : 兄弟姐妹对兄弟姐妹
5. 数据库三范式
1. 第一范式(1NF) : 列不可拆分
2. 第二范式(2NF) : 唯一标识
3. 第三范式(3NF) : 引用主键
后1个范式,都是在前1个范式的基础上建立的
6. 数据库关系实现
1:1 实现 : 主外键关联,添加唯一约束
1:n 实现 : 主外键关联
m:n 实现 : 通过中间表实现
2. 事务和事务回滚
2. 事务和事务回滚
1. 定义 : 一件事从开始发生到结束的过程
2. 作用 : 确保数据的一致性
3. 应用
1. 开启事务
mysql> begin;
2. 终止事务
mysql> commit; | rollback;
3. 案例
1. 背景
你 : 建行卡
你朋友 : 工商卡
你到建行自动取款机给你朋友转5000
2. 建表
表1 : CCB name money
表2 : ICBC name money
3. 转账过程
mysql> 点击转账按钮
mysql> begin;
mysql> update CCB set money=money-5000 where name="有钱人";
mysql> update ICBC set money=money+5000 where name="穷人";
mysql> commit; 转账成功
4. 注意
事务只针对于表记录操作(增删改)有效,对于库和表的操作无效
3. 与Python交互
3. 与Python交互
1. python3 : pymysql(模块名)
python2 : MySQLdb(模块名)
2. 安装
1. 在线 : sudo pip3 install pymysql
sudo pip install mysql-python
2. 离线 : pymysql-0.9.1.tar.gz
$ tar -zxvf pymysql-0.9.1.tar.gz
$ cd pymysql0.9.1
$ sudo python3 setup.py install
3. 环境准备
1. 创建库 db5 , utf8
create database db5 charset utf8;
2. 创建表 t1
use db5;
create table t1(
id int primary key auto_increment,
name varchar(20),
score float(5,2)
);
3. 在表中插入3条记录
insert into t1(name, score) values
("李白",60),("杜甫",75),("白居易",80);
1. pymysql使用
4. pymysql使用流程
1. 数据库连接对象 : db = pymysql.connect(...)
2. 游标对象 : cur = db.cursor()
3. 执行命令 : cur.execute('sql命令')
4. 提交 : db.commit()
5. 关闭游标 : cur.close()
6. 断开连接 : db.close()
5. pymysql.connect()参数
1. host : 主机地址 host="localhost"
2. user : 用户名 user="root"
3. password : 密码 password="123456"
4. database : 库名 database="db5"
5. charset : 字符集(推荐utf8) charset="utf8"
6. port : 端口号(3306) port=3306
6. 数据库连接对象(db)的方法
1. db.cursor() : 创建游标对象
2. db.commit() : 提交到数据执行
3. db.rollback() : 回滚
4. db.close() : 断开与数据库连接
7. 游标对象(cur)的方法
1. cur.execute(sql命令) : 执行sql命令
cur.execute(sql,[]) : 第二个参数一定要为列表
2. cur.close() : 关闭游标对象
3. cur.fetchone() : 取1条(查询语句) 元组
4. cur.fetchmany(n) : 取n条 大元组中有小元组
5. cur.fetchall() : 取所有 大元组,有小元组
# fetchall()如果只有1个记录,((5,"小姐姐",100),)
result=((5,"小姐姐",100),)
result[0][1]
4. MySQL调优
4. MySQL调优
1. 选择合适的存储引擎
1. 读操作多 : MyISAM
2. 写操作多 : InnoDB
2. 创建索引
在select where order by常涉及到的字段建立索引
3. SQL语句优化(避免全表扫描)
1. where子句中,不使用!=,否则放弃索引全表扫描
2. 尽量避免NULL判断,否则...
优化前 : select num from t1 where num is null;
优化后
在num字段上设置默认值0,确保num字段无空值
select num from t1 where num=0;
3. 尽量避免 or 连接条件,否则... ...
优化前 : select id from t1 where id=10 or id=20
优化后 :
select id from t1 where id=10
union all
select id from t1 where id=20;
4. 模糊查询尽量避免使用前置%,否则...
select name from t1 where name like "%c%";
5. 尽量避免使用 in 和 not in
select id from t1 where id in(1,2,3,4);
用 between 1 and 4 代替
6. 尽量避免使用 select * ... ,不要返回用不到的任何字段
5. WorkBench图形化界面管理工具
5. WorkBench图形化界面管理工具
Navicat
6、MongoDB-数据库
Day01
MongoDB (芒果数据库)
1. 数据存储阶段
文件管理阶段 (.txt .doc .xls):
优点 : 数据可以长期保存
存储数据量大
使用简单
缺点 : 数据的存储结构随意
数据的查找,修改效率低
不方便扩展和自动化处理
数据库管理阶段
优点 : 数据格式化存储,便于操作
降低数据的冗余,提高操作效率
方便程序调用
缺点 : 使用需要特定的语句或者命令
2. 几个概念
数据: 能够输入到计算机中并被识别处理的信息集合
数据结构: 研究一个数据集合中,数据之间关系的学科
数据库: 按照数据结构,存储管理数据的仓库.数据库是在数据库管理系统管理控制下,在一定介质上创 建的数据集合
数据库管理系统 : 数据库管理软件,用户维护建立数库
数据库系统 : 由数据库及管理系统,开发工具等构成的集合
关系型数据库
采用关系模型来组织数据结构的数据库(二维表)
e.g. Oracle DB2 SQLServer MySql SqLite
优点: 1. 容易理解,逻辑类似常见的表格
2. 使用方便,都是用sql语句进行数据操作,sql语句很成熟
3. 数据一致性高,冗余低,完整性好
4. 技术成熟,可以使用表的外键关联等操作
缺点: 1. 每次数据操作都需要sql解析,消耗较大
2. 关系型数据库内部往往进行加锁处理,也影响处理速度
3. 不能很好的处理海量数据的高并发需求,读写能力差
4. 由于数据的一致性等规定,导致灵活性不高
非关系型数据库 (NoSql–>Not only sql)
优点 : 并发能力强,读写速度快,可以更好的应对海量数据并发
使用灵活,容易扩展
缺点 : 通用性差,没sql那样的统一语句
技术成熟度比关系型数据库低,没有外键等复杂操作
Nosql 分类:
键值型数据库: Redis
列存储数据库: HBase
文档型数据库: MongoDB
图形数据库: Graph
Nosql使用情况:
1. 对数据一致性要求低
2. 需要应对高并发的海量数据存储
3. 比较容易建立非关系模型
3. MongoDB数据库
MongoDB数据库
特点 : 1. 由c++编写的数据库管理系统
2. 支持丰富的增删改查操作
3. 有丰富的数据存储类型,技术相对成熟
4. 支持众多的编程语言接口
5. 使用方便,便于部署扩展
4. MongoDB的安装
linux : sudo apt-get install mongodb
安装位置: /var/lib/mongodb
配置文件: /etc/mongodb.conf
命令集: /usr/bin
手动安装: 1. www.mongodb.com 下载对应系统的安装 包
2. 将下载的安装包安装即可
压缩包解压到 /usr/local 目录
安装包 : sudo dpkg -i xxxx.deb
3. 添加环境变量
PATH=$PATH:/opt/mongodb/bin
export PATH
将以上两句放到 ~/.bashrc
5. MongoDB 命令
1.数据库设置命令 : mongod
2.设置数据库存储位置
mongod --dbpath 目录
3.设置端口号
mongod --port 端口
4.* mongodb默认端口 27017
5.启动mongo shell : mongo
6.退出 : ctrl-c quit()
6. mongodb数据库结构
键值对 --> 文档 --> 集合 --> 数据库
-------------------------
ID | NAME | AGE
-------------------------
1 | Lily | 18
-------------------------
2 | Lucy | 17
-------------------------
{
"_id":1,
"NAME":'Lily',
"AGE":18
},
{
"_id":2,
"NAME":'Lucy',
"AGE":17
}
mysql mongodb 含义
database database 数据库
table collection 表/集合
column field 字段/域
row document 记录/文档
index index 索引
7. 数据库操作
1.use database
e.g. 创建一个叫stu的数据库
use stu
* use实际是选择一个数据库.当这个数据库不存在时会 自动创建
* 使用use创建数据库,并不会马上创建,而是当插入数 据时才会真正被创建
查看数据库: show dbs
2.命名规则:
1. 使用utf-8字符
2. 不能含有空格 . / \ '\0'字符
3. 长度不超过64字节
4. 不要和系统数据库重名
3.全局变量db : 代表当前正在使用的数据库
* 如果不选择任何数据库,db默认为test
4.删除数据库: db.dropDatabase() 删除当前数据库
数据库的备份和恢复
1.备份命令 : mongodump -h dbhost -d dbname -o dir
e.g. 备份本机数据库 stu 到 student目录下
mongodump -h 127.0.0.1 -d stu -o student
2.数据库文件恢复:
mongorestore -h dbhost:port -d dbname dir
e.g.恢复stu目录下的数据到当前主机的student数据库
mongorestore -h 127.0.0.1:27017 -d student ./stu
数据库监控命名
mongostat 查看数据库运行状态
insert query update delete: 每秒执行增查该删次数
command : 每秒mongodb命令次数
flushes : 和磁盘交互情况
vsize : 使用的虚拟内存
res : 物理内存
time : 时间
mongotop 检测每个数据库中数据集合的读写情况
ns : 集合
total : 总时长
reas : 读时长
write : 写时长
8. 集合操作
1.创建集合
方法1 : db.createCollection(collection)
e.g. 创建一个名为class1的集合
db.createCollection('class1')
方法2 : 当插入数据时,需要指定集合,如果集合不存在则自动创建
e.g. 创建一个名为class2的集合
db.class2.insert({'name':'Lucy','age':17})
2.查看数据库中集合:
show collections
show tables
集合命名规则:
1. 使用utf-8字符
2. 不能含有 \0 字符
3. 不要以 system. 开头,这是系统集合名
4. 不要和关键字重复
3.删除集合 : db.collection.drop()
e.g. 删除class2集合
db.class2.drop()
4.集合重命名:
db.collection.renameCollection('new_name')
e.g. 将class集合改名为class0
db.class.renameCollection("class0")
9. 文档
什么是文档?
* 文档是mongodb数据库中基本的数据组成形式
* 文档是由键值对构成,每个键值对表达一项数据
* mongodb中文档为bson数据类型
键 : 即文档的域,表示值是什么内容
命名规则:
1. 使用utf-8字符串
2. 不能有\0
3. 一个文档中的键不能重复
4. 通过键取值,但是键值对位置不同认为是 不同文档
值 : 即数据库存储的数据
类型 值
数字 整数,小数
布尔类型 true false
Array 数组
String 字符串
Binary data 二进制字串
date 时间类型
Timestamp 时间戳
Null 空 null
Object 对象 内部文档
regex 正则表达式
code js代码
ObjectId ObjectId字串
ObjectId :
"_id" : ObjectId("5bf8ef43c365c39876c13e13")
_id :插入文档是自动添加的文档主键域
值 : ObjectId类型数据,保证和其他的主键值不重复
24位16进制码
8位文档创建事件,6位机器id,4位进程id,6位计数器
集合中的文档
1.集合中的文档
1. 每个集合中的文档格式可以不同(域名称,多少,种类)
2. 一个集合中的文档尽量体现相同的存储内容
3. 文档的表达层次尽量不要过于复杂
2.插入文档
1.插入单个文档: db.collection.insertOne()
功能: 插入一条文档
参数: 要插入的文档
e.g. 向class0中插入一条文档
db.class0.insertOne({'name':'Joy','age':18,'sex':'m'})
* db.class0.find() 查看插入结果
* 操作数据时键的引号可以省略
* _id可以自定义值,但是不能重复
* 一个集合中的文档是有序的
2.插入多条文档: db.collection.insertMany([{},{}..])
功能: 同时插入多条文档
参数: 数组中包含多个文档
e.g. 同时插入两条文档
db.class0.insertMany([{name:'Tom',age:19,sex:'m'},{name:'Jame',age:18,sex:'m'}])
3. 插入文档 : db.collection.insert()
功能: 插入文档
参数: 同insertOne + insertMany
e.g. 可以插入一条或者多条文档
db.class0.insert({"name":'Lily',age:17,sex:'w'})
3.save插入文档
db.collection.save()
功能: 插入文档,用法同insert()
参数: 同insert()可以插入一条或者多条文档
e.g. 如果指定的_id值存在,则替换原文档
db.class0.save({_id:1,name:'Tony',age:18})
获取集合对象
获取集合对象
db.getCollection(collection_name)
功能: 获取集合对象
e.g.
db.getCollection('class0') ==> db.class0
作业: 复习下mysql数据库操作
对比关系型和非关系型数据库差别
复习mongodb命令
复习:
1. 关系型数据库和非关系型数据库的比较
* 不是关系模型构建的数据库,不保证数据的一致性,结构 更加灵活自由
* 非关系型数据库弥补了关系型数据库在处理高并发数据 时读写效率低的问题
* 非关系型数据库种类多样,技术不如关系型数据库成熟, 没有统一的操作语句
2. MongoDB特点,安装,基本设置
3. 创建数据库
use database
db.dropDatabase() 删除数据库
show dbs 查看数据库
mongodump 备份
mongorestore 恢复
mongostat 数据库监测
mongotop 数据库读写时长
4. 集合操作
db.createCollection() 创建集合
db.collection.insert() 插入数据自动创建集合
db.getCollection() 获取集合对象
db.collection.drop() 删除集合
db.collection.renameCollection() 集合重命名
show collections 查看集合
5. 文档
什么是文档?
文档数据类型
插入文档:
insertOne()
insertMany()
insert()
save()
Day02
1. 查找操作
mysql: select ... from table where ...
mongodb: db.collection.find(query,field)
查找集合中所有内容
db.collection.find() --> select * from table
find(query,field)
功能: 查找所有符合条件的数据
参数: query : 表示筛选条件,是一个键值对文档,默认表 示查找所有内容
e.g. 查找年龄等于18的文档
db.class0.find({age:18})
field : 表示要查找哪个域,是一个文档键值对. 用0表示不查找的域,1表示查找的域
e.g. 表示不查找_id域,只查找name域
db.class0.find({age:18},{_id:0,name:1})
* 当某个域设置为0时表示该域不查找,其他的 域查找,如果设置为1表示该域查找,其他的不 查找
* _id比较特殊,如果不想查找必须设置为0
* 普通域0和1不能同时出现
findOne(query,field)
功能: 查找第一条符合条件的文档
参数: 同find
e.g. 查找第一条年龄18的文档
db.class0.findOne({age:18},{_id:0})
2. query的筛选功能
操作符 : 使用$符号注明的一个有特殊意义的字符串,用以表 达丰富的含义. 比如 $lt 表示小于
比较操作符:
$eq 等于 ==
e.g. 等于18
db.class0.find({age:{$eq:18}},{_id:0})
$lt 小于
e.g. 姓名小于Lily (字符串也可以比较大小)
db.class0.find({name:{$lt:'Lily'}},{_id:0})
$gt 大于 >
$lte 小于等于 <=
$gte 大于等于 >=
$ne 不等于 !=
e.g. 查找年龄大于等于18 小于等于20的
db.class0.find({age:{$gte:18,$lte:20}},{_id:0})
$in 包含
e.g. 年龄为14,16,18的
db.class0.find({age:{$in:[14,16,18]}},{_id:0})
$nin 不包含
e.g. 年龄不为14,16,18的
db.class0.find({age:{$nin:[14,16,18]}},{_id:0})
逻辑操作符
逻辑与
1. 在query中多个逗号隔开的键值对即逻辑与关系
e.g. 年龄17 并且 性别为女
db.class0.find({age:17,sex:'w'},{_id:0})
2. $and 表示逻辑与
e.g. 年龄17 并且 性别为女
db.class0.find({$and:[{age:17},{sex:'w'}]},{_id:0})
逻辑或 $or
e.g. 年龄大于17 或者性别为女
db.class0.find({$or:[{age:{$gt:17}},{sex:'w'}]},{_id:0})
逻辑非 $not
e.g. 查找年龄不小于18的
db.class0.find({age:{$not:{$lt:18}}},{_id:0})
逻辑既不也不 $nor not (A or B)
e.g. 年龄不为18 性别不为女
db.class0.find({$nor:[{age:18},{sex:'w'}]},{_id:0})
条件混合
年龄大于18或者年龄小于17 并且要求性别为m
db.class0.find({$or:[{age:{$gt:18}},{age:{$lt:17}}],sex:'m'},{_id:0})
年龄大于等于18的男生,或者叫Sunny
db.class0.find({$or:[{age:{$gte:18},sex:'m'},{name:'Sunny'}]},{_id:0})
数组查找
数组查找
数组 : 一组数据的有序集合,使用[]表示
* 有序的 可以用[]取值
* 数据类型可以不同
查找数组中包含某一项
e.g. 查找score数组中包含90的文档
db.class1.find({score:90},{_id:0})
$all 数组中同时包含多项
e.g. 数组中同时包含90 88 的
db.class1.find({score:{$all:[90,88]}},{_id:0})
$size 根据数组项目查找
e.g. 查找数组中包含3项的文档
db.class1.find({score:{$size:3}},{_id:0})
$slice 选择数组的查询部分 (用于field参数)
e.g. 显示数组中的前两项
db.class1.find({},{_id:0,score:{$slice:2}})
e.g. 跳过第一项显示后面两项
db.class1.find({},{_id:0,score:{$slice:[1,2]}})
其他查找操作符
其他查找操作符
$exists 判断一个域是否存在
e.g. 查找不存在sex域的文档 (true表示存在false表示 不存在)
db.class0.find({sex:{$exists:false}},{_id:0})
$mod 通过除数和余数筛选
e.g. 筛选年龄为单数的文档
db.class0.find({age:{$mod:[2,1]}},{_id:0})
$regex 根据正则表达式筛选
e.g. 简单的正则表达式筛选中间带o的
db.class0.find({name:{$regex:/.*o.*/}},{_id:0})
$type 根据数据类型筛选
e.g 查找age域值类型为 1 的
db.class1.find({age:{$type:1}},{_id:0})
* 类型和数据联系参加数据类型表
* 通过 www.mongodb.com --> docs查找新的操作符用法
数据处理函数
数据处理函数
db.collection.distinct(field)
功能: 获取某个域的取值范围
e.g. 查看age域的取值情况
db.class0.distinct('age')
pretty()
功能: 将find查询结果格式化显示
e.g. 格式化显示查询结果
db.class0.find().pretty()
limit(n)
功能: 显示查询结果的前n条
e.g. 显示查询结果前4条
db.class0.find({},{_id:0}).limit(4)
skip(n)
功能: 跳过前n条显示后面的内容
e.g. 跳过前4条显示后面的内容
db.class0.find({},{_id:0}).skip(4)
count()
功能 : 统计查询结果数量
e.g. 统计年龄18的文档个数 (写删选条件)
db.class0.find({age:18},{_id:0}).count()
sort({field:1/-1})
功能 : 对查找结果按照某个域的值排序 1表示升序 -1 降序
e.g. 查找结果按照年龄降序排列
db.class0.find({},{_id:0,sex:0}).sort({age:-1})
* 复合排序
e.g. 当第一排序项相同时按照第二排序项排序
db.class0.find({},{_id:0,sex:0}).sort({age:1,name:1})
查询结果操作函数可以连续条用
* 当前一个函数返回的仍然是查询结果集合,则可以继续调用函数操作
e.g. 查找年龄最大的三个文档
db.class0.find({},{_id:0,sex:0}).sort({age:-1}).limit(3)
可以通过序列号直接获取查询结果某一项
e.g. 获取第三个查询结果
db.class0.find({},{_id:0,sex:0})[2]
练习:
1. 创建数据库 名字 grade
user grade
2. 在数据库中创建集合 class
3. 集合中插入若干数据,格式如下
{name:xxx,age:xx,sex:'m',hobby:['xxx','xxx']}
age: 7-15岁之间
hobby: draw dance running sing football
basketball computer python
db.class.insert({name:'小明',age:8,sex:'m',hobby:['draw','sing']})
4. 查找练习
查看班级所有人信息
db.class.find()
查看班级中年龄为8岁的学生信息
db.class.find({age:8})
查看年龄大于10岁的学生信息
db.class.find({age:{$gt:10}})
查看年龄在10-14岁之间的学生信息
db.class.find({age:{$gte:10,$lte:14})
查看年龄为9岁且喜欢画画的女生
db.class.find({age:9,hobby:'draw',sex:'w'})
查看年龄小于8岁或者大于12的学生
db.class.find({$or:[{age:{$lt:8}},{age:{$gt:12}}]})
查看年龄为9岁或者11岁的学生
db.class.find({age:{$in:[9,11]}})
找到有两项兴趣的学生
db.class.find({hobby:{$size:2}})
找到喜欢计算机的学生
db.class.find({hobby:'computer'})
找到既喜欢跳舞又喜欢画画的学生
db.class.find({hobby:{$all:['dance','draw']}})
统计兴趣爱好有三项的学生人数
db.class.find({hobby:{$size:3}}).count()
找到班级中年龄第二大的同学
db.class.find().sort({age:-1}).skip(1).limit(1)
查看班级中兴趣爱好的涵盖范围
db.class.distinct('hobby')
找到班级中年龄最小的三个男生
db.class.find({sex:'m'}).sort({age:1}).limit(3)
3. 删除文档
删除文档
mysql : delete from table where ...
mongo : db.collection.deleteOne(query)
deleteOne(query)
功能 : 删除第一条符合条件的文档
参数 : 筛选条件 用法同find query
e.g. 删除第一条年龄为18岁的文档
db.class0.deleteOne({age:18})
deleteMany(query)
功能: 删除所有符合条件的文档
参数: query
e.g. 删除所有姓名以L开头的文档
db.class0.deleteMany({name:{$regex:/L.*/}})
* 如果筛选条件为空,表示删除集合中所有文档
e.g. 删除spider中所有内容
db.spider.deleteMany({})
remove(query,justOne)
功能: 删除文档
参数: query
justOne 默认为false此时remove==deleteMany
设置为true 此时remove==deleteOne
e.g. 删除第一个年龄为18的文档
db.class0.remove({age:18},true)
findOneAndDelete(query)
功能: 查找第一个符合条件的文档并且删除
参数: query
返回: 找到的文档
e.g. 查找不存在sex域的文档并且删除
db.class0.findOneAndDelete({sex:{$exists:false}})
删除练习:
使用grade数据库
删除年龄小于8岁或者大于15岁的同学
deleteMany({$or:[{age:{$lt:8}},{age:{$gt:15}}]})
删除兴趣爱好只有1项的同学
deleteMany({hobby:{$size:1}})
查找喜欢Python的同学并删除
findOneAndDelete({hobby:'python'})
修改操作
mysql : update table set... where...
mongo : db.collection.updateOne(query,update,upsert)
updateOne(query,update,upsert)
功能: 修改第一个符合条件的文档
参数: query 数据筛选
update 要修改的数据,需要配合修改操作符使用
upsert bool值,默认为false表示如果没有筛选到文
档则不执行操作.如果设置为true则没有筛
选到文档,根据query和update插入新的文档
e.g. 修改han的性别为w
db.class0.updateOne({name:'Han'},{$set:{sex:'w'}})
e.g. 如果没有找到Levi 则upsert表示插入新文档
db.class0.updateOne({name:'Levi'},{$set:{age:16}},{upsert:true})
updateMany(query,update,upsert)
功能 : 修改所有符合条件的文档
参数 : 同updateOne
e.g. 修改所有年龄为16的 为 19
db.class0.updateMany({age:16},{$set:{age:19}})
update(query,update,upsert,multi)
功能: 修改文档
参数: query,update 同updateOne
upsert bool值 true表示插入新文档
multi 默认为false 此时同updateOne
设置为true 同updateMany
e.g. 修改所有性别为m的年龄为19
db.class0.update({sex:'m'},{$set:{age:19}},true,true)
findOneAndUpdate(query,update)
功能: 查找一个文档并修改
参数: query 查找文档
update 修改内容
返回 : 修改前的文档
e.g. 查找并修改一个文档
db.class0.findOneAndUpdate({name:"Levi"},{$set:{age:16}})
findOneAndReplace(query,document)
功能: 查找一个文档并替换
参数: query 筛选条件
document 替换的文档
返回: 原来的文档
e.g. 替换姓名为Abby的文档
db.class0.findOneAndReplace({name:'Abby'},{name:'Lily',age:15,sex:'w'})
作业 : 复习mongodb的增删改查
将'三国'建立mongo数据库,进行响应的增删改查练习
前情回顾
1. 数据库查找
find(query,field)
findOne(query,field)
2. query使用
操作符:
比较: $eq $lt $gt $lte $gte $in $nin
逻辑: $and $or $not $nor
数组: $all $size
其他: $exists $mod $regex $type
3. 数据处理函数: pretty() limit() skip() sort()
count() distinct()
4. 删除操作: deleteOne() deleteMany() remove()
findOneAndDelete()
5. 修改操作: updateOne() updateMany() update()
findOneAndUpdate() findOneAndReplace()
Day03
1. 修改器的使用
db.collection.updateOne(query,update,upsert)
$set : 修改一个域的值,或者增加一个域
e.g. 修改sex域的值,如果不存在会增加这个域
db.class0.updateOne({name:'Levi'},{$set:{sex:'m'}})
$unset : 删除一个域
e.g. 删除Jame的sex域
db.class0.updateOne({name:'Jame'},{$unset:{sex:''}})
$rename: 修改域的名称
e.g. 修改sex域名为gender
db.class0.updateMany({},{$rename:{sex:'gender'}})
$setOnInsert: 当update插入文档时作为补偿内容插入
e.g. 如果执行了插入操作则插入补充内容
db.class0.updateOne({name:'Joy'},{$set:{age:20},$setOnInsert:{gender:'m',tel:88668866}},{upsert:true})
$inc : 加法修改器
$inc : 加法修改器
e.g. 所有人年龄加1
db.class0.updateMany({},{$inc:{age:1}})
$mul : 乘法修改器
$mul : 乘法修改器
e.g. 所有人年龄乘以1.5
db.class0.updateMany({},{$mul:{age:1.5}})
* $inc $mul 作用值可以是整数小数正数负数
$max : 指定某个域的值,如果小于指定值则改为指定值,大 于指定值则不做修改
e.g. 将所有年龄小于28的修改为28
db.class0.updateMany({},{$max:{age:28}})
$min : 指定某个域的值,如果大于指定值则修改为指定值, 如果小于指定值不变
e.g. 将所有年龄大于30的修改为30
db.class0.updateMany({},{$min:{age:30}})
数组修改器
数组修改器
$push : 向数组中添加1项
e.g. score数组中增加5
db.class1.update({name:'小明'},{$push:{score:5}})
$pushAll : 向数组中增加多项
e.g. score数组中增加多项
db.class1.update({name:'小红'},
{$pushAll:{score:[5,10]}})
$pull: 从数组中删除一个值
e.g. 删除score中的5
db.class1.update({name:'小明'},{$pull:{score:5}})
$pullAll: 从数组中删除多项值
e.g. 删除score数组中的5,10
db.class1.update({name:'小红'},{$pullAll:{score:[5,10]}})
$pop : 弹出数组中的一项
e.g. 弹出数组中的一项(1表示最后一项,-1第一项)
db.class1.update({name:'小刚'},{$pop:{score:-1}})
$addToSet : 向数组中添加一项,但是不能添加已有内容
e.g.向数组中添加92,要求不和已有数据重复
db.class1.update({name:'小刚'},{$addToSet:{score:92}})
$each : 对多个值逐一操作
e.g. 向数组中添加 90 和 10
db.class1.update({name:'小明'},{$push:{score:{$each:[90,10]}}})
$position: 指定数据的插入位置 搭配each使用
e.g. 指定插入数据的位置插入5
db.class1.update({name:'小红'},{$push:{score:{$each:[5],$position:1}}})
$sort : 对数组进行排序 搭配each使用
e.g. 对数组进行排序操作
db.class1.update({name:'小明'},{$push:{score:{$each:[],$sort:1}}})
2. 时间类型
获取当前时间:
获取当前时间:
1. new Date() 自动生成当前时间
e.g. 插入当前时间
db.class2.insert({"book":'Python入门',date:new Date()})
2. ISODate() 自动获取当前时间
e,g, 获取当前时间
db.class2.insert({"book":'Python精通',date:ISODate()})
3. Date() 获取系统时间生成字符串
e.g. 获取当前的系统时间
db.class2.insert({"book":'Python疯狂',date:Date()})
获取任意时间:
获取任意时间:
ISODate()
功能: 将指定的时间转换为mongodb时间格式存储
参数: 时间字符串
"2018-01-01 01:12:12"
"20180101 11:11:11"
"20180101"
e.g. 存储指定的时间
db.class2.insert({"book":'Python崩溃',date:ISODate('2018-01-01 12:12:12')})
时间戳:
时间戳:
valueOf() :将标准时间转换为时间戳
e.g. 获取标准时间时间戳
db.class2.insert({"book":'Python涅槃',date:ISODate().valueOf()})
3. Null类型
Null类型:
值 : null
1.表示某个域的值为空
e.g. 表示一个域的值为空
db.class2.insert({"book":'Python放生',price:null})
2. 表示某个域不存在的情况
e.g. 表示price域值为null 或者 不存在该域
db.class2.find({price:null},{_id:0})
4. 内部文档 (Object)
内部文档 (Object)
文档中某个域的值还是一个文档,则这个文档为内部文档
* 当使用内部文档某个域时需要外部文档 . 引用内部文 档,此时需要加引号操作
e.g. 通过书名查找
db.class3.find({"book.title":'茶馆'})
e.g. 修改操作
db.class3.update({'book.title':'茶馆'},{$set:{'book.price':42}})
5. 数组的下标引用
数组的下标引用
*数组也可以通过直接.引用下标的方式操作具体某一项
e.g. 修改数组中下标为1的项
db.class1.update({name:'小红'},{$set:{'score.1':10}})
# 练习
基于之前的grade 数据库
1. 将小红年龄修改为8 兴趣爱好变为跳舞画画
update({name:'小红'},{$set:{age:8,hobby:['dance','draw']}})
2. 追加小明兴趣唱歌
update({name:'小明'},{$push:{hobby:'sing'}})
3. 小王多了兴趣爱好吹牛 打篮球
update({'name':'小王'},{$pushAll:{hobby:['brag','basketball']}})
4. 小李兴趣爱好要增加跑步唱歌,但是不要和之前的重复
update({name:'小李'},{$addToSet:{hobby:{$each:['running','sing']}}})
5. 该班级所有同学年龄加1
updateMany({},{$inc:{age:1}})
6. 删除小明的sex属性
update({name:'小明'},{$unset:{sex:''}})
7. 删除小李兴趣中的第一个
update({name:'小李'},{$pop:{hobby:-1}})
8. 删除小红的兴趣画画唱歌
update({name:'小红'},{$pullAll:{hobby:['draw','sing']}})
9. 增加小红兴趣爱好 Python 为第一项兴趣
update({name:'小红'},{$push:{hobby:{$each:['python'],$position:0}}})
10. 为小王增加一个域 备注:{民族:'回族',习俗:'回族餐'}
update({name:'小王'},{$set:{备注:{民族:'回族',习俗:'回族餐'}}})
11. 在小王备注中增加一项 '宗教':'伊斯兰'
update({name:'小王'},{$set:{'备注.宗教':'伊斯兰'}})
6. 索引
索引
什么是索引?
索引是建立文档所在位置的查找清单,使用索引可以方便的进行快速查找,减少遍历次数,提高查找效率
索引约束
1. 索引本身占用数据库空间.所以当数据库很小时 没必要创建索引
2. 如果数据修改,索引表也要随之修改,否则索引就 没有意义.因此索引会降低数据写入的效率.如果 数据库操作时频繁的写操作而不是读操作则没有 必要创建索引
创建索引
创建索引
db.collection.createIndex()
功能: 创建索引
参数: 索引域 和 索引选项
e.g. 为name域创建索引
db.class0.createIndex({name:1})
* _id域会由系统自动创建索引
* 1 表示正向索引 -1为逆向索引
查看索引
查看索引 : db.collection.getIndexes()
自定义索引名称
e.g. 通过索引选项name定义名称
db.class0.createIndex({age:-1},{name:'ageIndex'})
删除索引
删除索引
db.collection.dropIndex()
功能: 删除一个索引
参数: 索引名称或者索引键值对
e.g. 通过键值对删除索引
db.class0.dropIndex({name:1})
e.g. 通过名称删除索引
db.class0.dropIndex('ageIndex')
db.collection.dropIndexes()
功能: 删除集合中所有索引
e.g. db.class0.dropIndexes()
其他创建索引方法
其他创建索引方法
ensureIndex()
功能: 创建索引
参数: createIndex()
createIndexes([{},{}])
功能: 同时创建多个索引
参数: 数组,存入多个索引键值对
e.g. 同时创建多个索引
db.class0.createIndexes([{name:1},{age:-1}])
* 一个集合中不能创建相同键值对的重复索引
索引类型
索引类型
复合索引 : 根据多个域创建一个索引
e.g 根据name age创建一个索引
db.class0.createIndex({name:-1,age:1},{name:"name_age"})
子文档,数组索引 : 如果对某个域创建索引,该域值为 数组或者内部文档.则对数组或者内部 文档中某一项的查询也是索引查询讯
e.g. 对book创建索引,该查询也是索引查询
db.class3.find({'book.title':'呐喊'})
唯一索引: 创建索引的域要求所有值不能重复
e.g. 对name创建唯一索引
db.class0.createIndex({name:1},{unique:true})
稀疏索引(间隙索引): 忽略没有指定索引域的文档
e.g. 对gender创建稀疏索引
db.class0.createIndex({gender:1},{sparse:true})
7. 聚合操作
聚合操作
对文档进行数据整理和统计
db.collection.aggregate()
功能: 完成聚合操作
参数: 聚合条件, 需要配合聚合操作符
聚合操作符:
$group 分组聚合 往往配合一个统计操作来完成
$sum 求和
e.g. 分组统计各个性别的人数
db.class0.aggregate({$group:{_id:'$gender',num:{$sum:1}}})
$avg 求平均数
e.g. : 按性别分组求平均年龄
db.class0.aggregate({$group:{_id:'$gender',num:{$avg:'$age'}}})
$max 求最大值
e.g. 按性别分组求每组最大年龄
db.class0.aggregate({$group:{_id:'$gender',num:{$max:'$age'}}})
$min 求最小值
$first 求第一个
$last 求最后一个
$project : 用于格式化的显示文档
* 值同find()的field参数用法
e.g. 以指定名称显示某个域的值
db.class0.aggregate({$project:{_id:0,Name:'$name',Age:'$age'}})
$match : 用于筛选想要的文档
* 值同find()函数query参数
e.g. 筛选年龄大于18的数据
db.class0.aggregate({$match:{age:{$gt:28}}})
$limit 显示前几条文档
e.g. 显示前3条文档
db.class0.aggregate({$limit:3})
$skip 跳过几条文档显示
e.g. 跳过前三条显示后面的文档
db.class0.aggregate({$skip:3})
$sort 按照域值排序
e.g. 按年龄升序排序
db.class0.aggregate({$sort:{age:1}})
聚合管道
聚合管道
指的是将多个聚合操作合并到一起完成,将上一个聚合的结果交给下一个聚合作为操作对象操作
db.collection.aggregate([{聚合1},{聚合2},{}....])
e.g. 将排序结果用project显示
db.class0.aggregate([{$sort:{age:1}},{$project:{_id:0,name:1,age:1}}])
1. 男生,按照年龄排序,显示结果不显示_id域
match--> sort -->project
db.class0.aggregate([{$match:{gender:'m'}},{$sort:{age:1}},{$project:{_id:0}}])
2. 统计班级所有重名的同学
group --> match
db.class0.aggregate([{$group:{_id:'$name',num:{$sum:1}}},{$match:{num:{$gt:1}}}])
#作业:
修改操作符数量使用
索引聚合操作练习
###
课程:MongoDB 日期:2018年11月28日 进度:day4 姓名:王丹波
========== 主要内容 ==========
1)固定集合: 限制集合的大小(理解,应用)
2)文件存储: 将文件内容存入数据库(重点,应用)
3)pymongo: 使用Python语言访问数据库
对数据库进行操作(重点,应用)
回顾之前的内容
1. 创建集合
acct: 账户集合
acct_no: 账号
acct_name: 户名
acct_type: 类型
balanc: 余额
1) 插入单笔
db.acct.insert({
acct_no:"622345111111",
acct_name:"Jerry",
acct_type:1,
balance:1234.56
})
2)插入多笔
db.acct.insert([
{
acct_no:"622345222222",
acct_name:"Tom",
acct_type:1,
balance:2000
},
{
acct_no:"622345333333",
acct_name:"Dokas",
acct_type:2,
balance:5000
}
])
3)save插入
db.acct.save({
acct_no:"622345444444",
acct_name:"Emma",
acct_type:2,
balance:10000
})
4)查找
带单个条件查找
db.acct.find({acct_no:"622345111111"})
select * from acct
where acct_no = '622345111111'
带多个条件的查询
db.acct.find({
acct_no:"622345111111",
acct_name:"Jerry"
})
查找金额小于5000元的账户
db.acct.find({balance:{$lt:5000}})
$and实现多个条件组合查询
db.acct.find({
$and:[{acct_type:1},{balance:1234.56}]
})
修改
db.acct.update(
{acct_no:"622345111111"},
{$set:{balanc:234.56}
}
)
乘法修改器
db.acct.update(
{acct_no:"622345444444"},
{$mul:{balance:1.02}}
)
5)上次课程内容:
查找: distinct 去重
e.g. db.acct.distinct("acct_type")
limit 显示前N笔数据
e.g. db.acct.find().limit(2)
count 统计笔数
e.g. db.acct.find({acct_type:1}).count()
sort 排序
e.g. db.acct.find().sort({balance:-1})
删除
db.collection.remove(query, justOne)
query: 筛选条件
justOne:是否删除一条,布尔值
db.acct.remove({acct_no:"622345444444"}, true)
修改
db.collection.update(query, update, upsert, multi)
query: 筛选条件
update: 修改内容
upsert: 查询不到数据时,是否执行插入
mult: 是否修改多条
db.acct.update(
{acct_no:"622345333333"},
{$set:{
balance:0,
acct_type:2,
close_date:new Date()
}},
false,false)
$set: 修改域
$unset: 删除域
$rename: 修改域名称
$inc: 加法修改器
$min: 用值的值进行比较,取较小的
$max: 用值的值进行比较,取较大的
$push/pushAll: 向数组添加值
$pull/pullAll: 从数组取出值
$each: 对多个值逐一取出,执行操作
$addToSet: 向数组添加数据,不和已有数据重复
时间类型:
- 计算中时间表示法: 整数,
表示从1970-01-01 00:00:00到当前时间点的描述/毫秒数
- Date() 取当前系统时间,字符串
- new Date() 生成当前时间,对象
- ISODate() 生成当前时间,对象
- ISODate().toLocaleString()
null类型: 字段不存在,值没有被设置
内嵌文档:
- 某个域的值还是一个文档
- 饮用方式: outer_doc.inner_doc.filed_name
索引:
- 概念: 键值和所在的文档位置的对照关系
- 作用: 提高数据查询效率(通过避免全表扫描)
- 索引的使用
- 创建: createIndex(key, option)
- 查看索引: db.collection.getIndexes()
- 删除索引: db.collection.dropIndex(name)
- 唯一索引:
db.collection.createIndex{{acct_no}, {unique:true}}
聚合: aggregate
$group: 分组统计
$sum: 对某个域求和
$max:
$min:
$avg: 求平均值
$project: 从集合查询制定的域
$match: 数据过滤
$sort:
管道聚合: 一个操作处理完成后,将结果送入下一个操作处理
db.acct.aggregate({$match:{acct_type:1}},
{$sort:{acct_no: -1}}
)
Day04
今天的内容
1. 固定集合:
- 有着固定大小的集合(大小, 笔数)
- 我们可以把固定集合想象成一个环形队列
当空间用完后,再插入的数据会覆盖头部的数据
- 应用:
临时缓存
日志
- 优点
插入速度快,顺序查找速度快
能够淘汰早期的数据
能够控制集合的大小
- 创建固定集合
- 语法:db.createCollection(collection,
{capped:true, size:10000, max:3}
)
collection: 集合名称
capped: 表示创建固定集合
size: 集合的大小,单位字节(Byte)
max: 最多存放多少文档
- 示例:
第一步:创建日志集合
db.createCollection('log',
{capped:true, size:10000, max:3}
)
第二步:插入3笔数据(前面三笔插入成功)
db.log.insert({
oper_date: new Date(),
user_id:"Tom",
oper: "insert"
})
第三步:插入第4笔数据(覆盖一笔之前的数据)
2. 文件存储
1) 文件存储的方式
- 数据库中只存储文件路径,文件存储某个目录下
优点: 占用数据库空间较少
缺点: 存储路径和实际路径不一致时,文件丢失
- 将整个文件数据库存入数据库
优点: 数据库和文件绑定存在
缺点: 占用较多数据库空间
2) GridFS
-GridFS: 把文件存储到Mongo集合中的一种方式
-通常用来存储二进制文件,如图片,音乐,视频
-存储原理:将文件分解成多个小的片段(chunk)存储
一个片段大小一般为256K
每个片段作为一个文档存储在chunks集合中
-GridFS用两个集合来存储文件
- fs.file: 存储文件的元信息
- fs.chunks: 存储文件的实际内容
- 优缺点:
优点:能存储很大的文件
在分布式环境下,能自动同步文件元数据
仅加载文件部分内容即可读取,不必将整个文件加载到内存
缺点:
读取效率比从磁盘低,所以最好存储16M以上的文件
只能整体替换,无法局部更新
示例:
第一步: 准备二进制文件
(将一个tar.gz文件复制为tmp.tar.gz)
第二步: 将文件存入mongodb
mongofiles -d gridfs put tmp.tar.gz
第三步: 登录mongo, 进入gridfs数据库
检查是否保存(在fs.file集合下查看文件名,大小)
第四步: 删除本地文件
rm tmp.tar.gz
第五步: 从数据库 提取文件
mongofiles -d gridfs get tmp.tar.gz
提取成功后,该文件被存储到本地目录
参数: -d 指定存取的数据库
put 存文件
get 取文件
tmp.tar.gz 文件路径
3. pymongo: 使用python操作MongoDB
1) 安装:
第一步: pip3 install pymongo
第二步: 验证安装
进入Python交互模式,输入import pymongo
如果不报错,则说明安装成功
2) pymongo访问数据库的步骤
第一步:创建mongodb的连接对象
第二步:获取数据库对象
第三步:获取集合对象
第四步:执行操作语句
第五步:关闭连接
示例1: 显示数据库服务器上所有的库
# show_dbs.py
# 显示mongo服务器上所有的数据库
import pymongo
# 1. 建立连接 MongoClient
# conn = pymongo.MongoClient(
# "mongodb://localhost:27017")
conn = pymongo.MongoClient("localhost", 27017)
# 2. 获取数据库列表
#dblist = conn.list_database_names()
dblist = conn.database_names()
for db in dblist: # 遍历, 打印
print(db)
# 3. 关闭数据库
conn.close()
print("数据库已关闭")
示例2: 查询
# find.py
# 查询
import pymongo
# 1. 连接数据库
conn = pymongo.MongoClient("localhost",27017)
# 2. 列出所有数据库
dblist = conn.database_names()
db = "test"
# 判断库是否存在
if db in dblist:
mydb = conn["test"] #获取数据库对象
mycol = mydb["acct"] #选择集合
# 查询, 打印
#docs = mycol.find({}, {"_id":0})
docs = mycol.find({"acct_no":"622345111111"},
{"_id":0})
for doc in docs:
print(doc)
else:
print("not found collection:", db)
conn.close()
插入
- insert() 插入一条或多条
- insert_one() 插入一条
- insert_many() 插入多条
- save() 如果id存在则覆盖,不存在则插入
示例3: 单笔插入
# insert.py
# Mongodb插入操作
import pymongo
# 1. 建立连接
conn = pymongo.MongoClient("localhost",27017)
# 2. 列出所有数据库
dblist = conn.database_names()
db = "test"
if db in dblist:
mydb = conn["test"] # 获取数据库对象
mycol = mydb["acct"] # 获取集合对象
# 定义插入的内容
mydict = {
"acct_no": "622345888888",
"acct_name": "David",
"balance":3333.33
}
ret = mycol.insert_one(mydict)
print(ret.inserted_id) # 打印新插入的ID号
else:
print("db not found")
conn.close()
示例4:
# insert_many.py
# Mongodb插入多行操作
import pymongo
# 1. 建立连接
conn = pymongo.MongoClient("localhost",27017)
# 2. 列出所有数据库
dblist = conn.database_names()
db = "test"
if db in dblist:
mydb = conn["test"] # 获取数据库对象
mycol = mydb["acct"] # 获取集合对象
# 定义插入的内容, 多笔传入列表参数
mydict = [
{"acct_no":"622345777", "acct_name":"Kevin"},
{"acct_no":"622345666", "acct_name":"Emma"}
]
ret = mycol.insert_many(mydict)# 插入多笔
print(ret.inserted_ids) # 打印新插入的ID号
else:
print("db not found")
conn.close()
修改:
修改:
- update(query, update,
upsert=False, multi=False)
query: 筛选条件
update: 修改内容
upsert: 是否执行插入
multi: 是否修改多行
代码:
# update.py
# 修改数据
import pymongo
# 连接数据库
conn = pymongo.MongoClient("localhost",27017)
# 列出所有数据库
dblist = conn.database_names()
db = "test" # 操作的数据库
if db in dblist:
mydb = conn["test"] # 获取数据库对象
mycol = mydb["acct"] # 获取集合对象
# 修改
myquery = {"acct_no":"622345111111"}
new_values = {"$set": {"balance":99.99}}
ret = mycol.update_one(myquery, new_values)
print("修改笔数:%d" % ret.modified_count)
else:
print("db not found")
conn.close()
删除:
删除:delete_one, delete_many
- delete_one(query)
query: 筛选条件
代码:
# delete.py
# 删除数据
import pymongo
# 连接数据库
conn = pymongo.MongoClient("localhost",27017)
# 列出所有数据库
dblist = conn.database_names()
db = "test"
if db in dblist:
mydb = conn["test"] # 获取数据库对象
mycol = mydb["acct"] # 获取集合对象
myquery = {"acct_no":"622345666",
"acct_name":"Emma"}
ret = mycol.delete_one(myquery)
print("删除笔数:%d" % ret.deleted_count)
else:
print("db not found")
conn.close()
示例:利用pymongo存取文件
- bson.binary: 可以将字符串转换为二进制存储
第一步:查找一张jpg格式的图片
cd ~
find . -name *.jpg
将图片复制到用户主目录:cp 文件路径 ~/
第二步:编写代码
# file_oper.py
# 将文件存入mongo, 并且取出
from pymongo import MongoClient
import bson.binary
from_img = "flower.jpg" # 原始图片名称
to_img = "new_flower.jpg"# 生成的新图片名称
def save_img(myset):
# 存储图片
f = open(from_img, "rb") # 只读,二进制方式打开
data = f.read() # 读文件内容
# 将data转换为mongodb的存储格式
content = bson.binary.Binary(data)
myset.insert({
"filename":from_img, # 文件名
"data":content # 文件数据
})
print("save ok")
return
def get_img(myset): # 从mongodb读取图片
img = myset.find_one({"filename":"flower.jpg"})
with open(to_img, "wb") as f:#打开存入文件
f.write(img["data"])#将data域写入文件
print("save new img ok")
return
# 连接数据库,取得数据库对象,取得集合对象
conn = MongoClient("localhost", 27017)
db = conn.gridfs # 取得数据库对象
myset = db.image # 取得集合对象
#save_img(myset) # 存储图片函数
get_img(myset) # 读取图片函数
conn.close()
#作业:
1)创建订单集合(名称orders),包含的域有:
order_id: 订单编号, 字符串
cust_name: 订单所属客户, 字符串
order_date: 下单时间,Date类型
status: 订单状态, 整数
order_detail: 订单明细, 文档数组
product_id: 商品编号, 字符串
product_name: 商品名称, 字符串
amt: 商品数量, 整数
price: 单价, 浮点数
2)插入3笔订单数据,每个订单至少包含1件商品
至少有一个订单包含多件商品(注意数据规范性)
3)编写下列语句
a)查找所有状态为1的订单
b)查找某个客户状态为1的订单(cust_name,status)
c)查找某个时间点以后下单的订单
d)统计订单笔数
e)修改某个订单的状态
f)为所有订单添加一个域:
支付状态(payment_status),整数
g)查询所有订单中,商品编号为"P0001"的订单
h)在订单集合的订单编号(order_id)域上创建升序索引
i)为某个订单增加备注信息(要求为字符串数组)
j)删除一笔无效订单(status判断,具体值自己定)
#明天课程准备:
github或https://gitee.com/上申请一个账号
###
日期:2018-11-29 课程:git 姓名:王丹波
------- 主要内容 -------
1. 版本管理工具git
2. 调试工具pdb
上次内容回顾
#1. 固定集合: 创建集合的时候,限定了大小,笔数
特点:
当集合空间用完后,新插入的数据会覆盖之前的数据
优点:
插入速度,顺序查找速度快
能够淘汰早期的数据
可以控制集合的大小
应用场景:
临时缓存,日志
创建语法:
db.createCollection(collection,
{capped:true, size:1000, max:100}
)
#2. 文件存储
1) 两种文件存储方式
- 数据库中存储文件路径,文件单独放到某个目录下
优点:节约数据库空间
缺点:存储路径和实际路径不一致时,文件丢失
- 将这个文件存入数据库
优点:数据库和文件绑定存在
缺点:占用数据库空间较多
2) GridFS: 用来将存取文件
- 将文件分割成多个片段,存储到数据库中
- 包含两个集合:
fs.file: 存储文件元信息(大小,片段数量,MD5值)
fs.chunks: 存储文件实际内容
- 示例:
存文件
mongofiles -d gridfs put tmp.tar.gz
取文件
mongofiles -d gridfs get tmp.tar.gz
#3. pymongo:Python操作MongoDB接口
查看pymongo版本:pip3 list | grep pymongo
- MongoClient: 返回数据库连接对象
e.g. conn = pymongo.MongoClient(host,port)
- list_database_names()
database_names()
获得服务器上所有数据库列表
- 获取数据库对象: mydb = conn["test"]
conn: 数据库连接对象
- 获取集合对象: mycol = mydb["acct"]
mydb: 数据库对象
- 插入:
insert(), insert_one(), inser_many()
save()
- 修改:
update(query, update,
upsert=False, multi=False)
query: 筛选条件
update: 修改的内容
upsert: 是否执行插入
multi: 是否修改多行
- 删除: delete_one, delete_many
- 查询: find()
#作业:
1)创建订单集合(名称orders),包含的域有:
order_id: 订单编号, 字符串
cust_name: 订单所属客户, 字符串
order_date: 下单时间,Date类型
status: 订单状态, 整数
order_detail: 订单明细, 文档数组
product_id: 商品编号, 字符串
product_name: 商品名称, 字符串
amt: 商品数量, 整数
price: 单价, 浮点数
2)插入3笔订单数据,每个订单至少包含1件商品
至少有一个订单包含多件商品(注意数据规范性)
db.orders.insert({
order_id:"201811200001",
cust_name:"Jerry",
order_date: new Date(),
status:1,
order_detail:[
{product_id: "P0001",
product_name:"水杯",
amt:1,
price:15.00
},
{product_id: "P0002",
product_name:"C语言编程",
amt:1,
price:65.00
}
]
})
db.orders.insert({
order_id:"201811200002",
cust_name:"Dokas",
order_date: new Date(),
status:1,
order_detail:[{
product_id: "P0003",
product_name:"手机",
amt:1,
price:1999.00
}]
})
3)编写下列语句
a)查找所有状态为1的订单
db.orders.find({status:1})
b)查找某个客户状态为1的订单(cust_name,status)
db.orders.find({
cust_name:"Jerry",
status:1
})
c)查找某个时间点以后下单的订单
db.orders.find({
order_date:{
$gt:ISODate("2018-11-20T08:29:45")}
})
d)统计订单笔数
db.orders.find().count()
e)修改某个订单的状态
db.orders.update(
{order_id:"201811200001"},
{$set:{status:2}})
f)为所有订单添加一个域:
支付状态(payment_status),整数
db.orders.update(
{},
{$set:{payment_status:null}},
false, true
)
g)查询所有订单中,商品编号为"P0001"的订单
db.orders.find({
"order_detail.product_id": "P0001"
})
h)在订单集合的订单编号(order_id)域上创建升序索引
db.orders.createIndex({order_id:1})
i)为某个订单增加备注信息(要求为字符串数组)
db.orders.update(
{order_id:"201811200001"},
{$pushAll:{remark:["工作日送达","后付款"]}}
)
j)删除一笔无效订单(status判断,具体值自己定)上次内容回顾
1. 固定集合: 创建集合的时候,限定了大小,笔数
特点:
当集合空间用完后,新插入的数据会覆盖之前的数据
优点:
插入速度,顺序查找速度快
能够淘汰早期的数据
可以控制集合的大小
应用场景:
临时缓存,日志
创建语法:
db.createCollection(collection,
{capped:true, size:1000, max:100}
)
2. 文件存储
1) 两种文件存储方式
- 数据库中存储文件路径,文件单独放到某个目录下
优点:节约数据库空间
缺点:存储路径和实际路径不一致时,文件丢失
- 将这个文件存入数据库
优点:数据库和文件绑定存在
缺点:占用数据库空间较多
2) GridFS: 用来将存取文件
- 将文件分割成多个片段,存储到数据库中
- 包含两个集合:
fs.file: 存储文件元信息(大小,片段数量,MD5值)
fs.chunks: 存储文件实际内容
- 示例:
存文件
mongofiles -d gridfs put tmp.tar.gz
取文件
mongofiles -d gridfs get tmp.tar.gz
3. pymongo:Python操作MongoDB接口
查看pymongo版本:pip3 list | grep pymongo
- MongoClient: 返回数据库连接对象
e.g. conn = pymongo.MongoClient(host,port)
- list_database_names()
database_names()
获得服务器上所有数据库列表
- 获取数据库对象: mydb = conn["test"]
conn: 数据库连接对象
- 获取集合对象: mycol = mydb["acct"]
mydb: 数据库对象
- 插入:
insert(), insert_one(), inser_many()
save()
- 修改:
update(query, update,
upsert=False, multi=False)
query: 筛选条件
update: 修改的内容
upsert: 是否执行插入
multi: 是否修改多行
- 删除: delete_one, delete_many
- 查询: find()
作业:
1)创建订单集合(名称orders),包含的域有:
order_id: 订单编号, 字符串
cust_name: 订单所属客户, 字符串
order_date: 下单时间,Date类型
status: 订单状态, 整数
order_detail: 订单明细, 文档数组
product_id: 商品编号, 字符串
product_name: 商品名称, 字符串
amt: 商品数量, 整数
price: 单价, 浮点数
2)插入3笔订单数据,每个订单至少包含1件商品
至少有一个订单包含多件商品(注意数据规范性)
db.orders.insert({
order_id:"201811200001",
cust_name:"Jerry",
order_date: new Date(),
status:1,
order_detail:[
{product_id: "P0001",
product_name:"水杯",
amt:1,
price:15.00
},
{product_id: "P0002",
product_name:"C语言编程",
amt:1,
price:65.00
}
]
})
db.orders.insert({
order_id:"201811200002",
cust_name:"Dokas",
order_date: new Date(),
status:1,
order_detail:[{
product_id: "P0003",
product_name:"手机",
amt:1,
price:1999.00
}]
})
3)编写下列语句
a)查找所有状态为1的订单
db.orders.find({status:1})
b)查找某个客户状态为1的订单(cust_name,status)
db.orders.find({
cust_name:"Jerry",
status:1
})
c)查找某个时间点以后下单的订单
db.orders.find({
order_date:{
$gt:ISODate("2018-11-20T08:29:45")}
})
d)统计订单笔数
db.orders.find().count()
e)修改某个订单的状态
db.orders.update(
{order_id:"201811200001"},
{$set:{status:2}})
f)为所有订单添加一个域:
支付状态(payment_status),整数
db.orders.update(
{},
{$set:{payment_status:null}},
false, true
)
g)查询所有订单中,商品编号为"P0001"的订单
db.orders.find({
"order_detail.product_id": "P0001"
})
h)在订单集合的订单编号(order_id)域上创建升序索引
db.orders.createIndex({order_id:1})
i)为某个订单增加备注信息(要求为字符串数组)
db.orders.update(
{order_id:"201811200001"},
{$pushAll:{remark:["工作日送达","后付款"]}}
)
j)删除一笔无效订单(status判断,具体值自己定)
7、Redis-数据库
8、Git-版本控制
Day05-Github
今天的内容
1. 版本管理工具git
1)什么是版本控制(Revision Control)
- 项目文档包含:
源码
文档(需求,设计,会议纪要,厂商联系方式)
软件包(开发工具,数据库,第三方库)
- 对各种软件所涉及到的文件进行管理
控制,变更记录,追溯
- 什么时候,什么人,修改了什么文件,什么内容
完整记录
配置管理岗: 专门进行配置管理
- 解决什么问题
- 版本管理规范性
- 解决版本更新,冲突
- 协调不同的开发者的变更,提高协同开发的效率
- 版本管理的相关术语
- 检出: 将软件配置(文件)从配置库中提取出来
- 检入: 将软件配置项(文件)放回配置库
- 主干版本: 标准配置库
- 分支版本: 为了某些特殊要求
和主干版本有差异的配置库
- 合并:
- A,B两个版本,将A的内容附加到B中
- A,B两个版本,A和B合并,形成新版本C
-历史记录:
文件变更的详细过程
-回滚:将配置退回到之前的某个状态
2) 版本管理方式
a)集中式管理
-配置库集中存放于中央服务器
-变更之前,先从中央服务器取得最新版本
然后进行变更,修改
-修改完成后,将变更提交到中央服务器
-缺点:集中式存放,必须联网,速度较慢
-典型工具:SVN
b)分布式
-没有中央服务器
-每个开发人员电脑都是一个完整配置库
-配置库位于本地,所以不一定需要联网
-每个开发者,可以将自己的代码贡献到
其他开发者仓库中
-典型工具:git
2.git: 分布式配置管理工具
1)更适合个人开发,管理配置库
2)分布式管理,不同svn的集中式管理
3)支持强大的分支功能
4)完整性优于svn
3.git安装:sudo apt-get install git
4.git配置
1)/etc/gitconfig文件:作用于系统所有用户
2)~/.gitconfig文件:用户目录下,作用于当前用户
3)工作目录下.git/config文件,作用于当前目录
优先级:工作目录>用户配置>系统配置
4)配置示例:
-git config --global user.name tarena
- git config --global user.email wangdb@tedu.cn
查看:cat ~/.gitconfig
- 查看已有配置: git config --list
5.git基本命令
1) init:
执行如下几个命令:
cd ~ # 进入用户主目录
mkdir gittest # 新建一个空目录
cd gittest
git init # 初始化,成功后当前会多出.git隐藏目录
2) add: 添加文件内容至索引
vim a.txt # 新建文本文件
git add a.txt # 将a.txt添加到仓库中
git status # 查看当前目录状态
3)commit: 提交变更至本地仓库
git commit 文件名 -m 注释信息
示例: git commit a.txt -m "create"
* 必须写注释
4)diff: 查看工作目录和仓库文件的差异
例如: git diff a.txt
5)reset: 版本的回滚
git reset --hard HEAD^ 回退到上一个版本
git reset --hard HEAD^^ 回退到上上一个版本
git reset --hard HEAD~n 回退到前面第n个版本
6. 分支管理
1)分支版本:有别于主版本,例如开发版,某个定制版
2)分支操作
- 查看所有分支: git branch
列出所有版本,带*表示当前所在分支
- 创建分支版本
git branch 分支版本名称
e.g.
git branch dev #创建名称为dev的分支版本
- 切换分支版本
git checkout 分支版本名称
e.g.
git checkout dev #切换到dev分支下
- 创建并切换分支
git checkout -b beta #创建并切换到beta分支下
- 版本合并:
git merge beta #把beta版本合并到当前分支
第一步: 进入到beta分支
git checkout beta
第二步: 修改a.txt,并提交(提交到beta分支)
第三步: 切换到dev分支
git checkout dev
第四步: 执行合并
git merge beta #把beta分支合并到当前分支
- 删除分支:
git branch -d beta
删除beta分支,如果没有合并则不允许删除
练习常用命令: init,add,commit,diff,checkout,log,status,reset
7. 标签管理
1)如果达到一个重要节点, 并希望永远记住那个提交
的快照, 可以使用标签
2)标签可以理解成一个指向某次提交的指针,
但不能移动
3)标签命令: git tag 标签名称.例如:
git tag v1.0 #将v1.0标签打到最新版本上
git tag #查看所有标签
git tag v0.9 0771ec3 #将v0.9标签打到制定的0771ec3版本上
git reset --hard v0.9 #退回到v0.9标签状态
8. github远程仓库
第一步:在gitee或github上注册账号
第二步:创建项目,并且拷贝地址
第三步:在工作目录下加入远程仓库地址
git remote add 名称 远程仓库地址
例如:
git remot add gitee https://gitee.com/bbsmil/git_test2.git
第四步:从远程仓库获取配置库
切换到master分支下,做一个pull操作
git pull 远程仓库名称 分支版本名称
例如: git pull gitee master
第五步: 修改工作目录文件,并且提交到本地仓库
例如: 修改a.txt后, 执行提交
git commit a.txt -m "remote test"
第六步: 推送到远程仓库
git push -u 远程仓库名称 分支版本
例如:git push -u gitee master
* 推送到gitee仓库的master分支下
9.调试工具
1)程序调试(debug): 程序在开发,测试,维护过程中
需要对程序测试,排除错误
2)调试工具:提高调试效率的工具
一般都能单步,打印变量,观察内部执行过程
3)pdb: Python自带的调试工具
4)使用:
- 启动调试: pdb3.5 tmp.py # 对tmp.py调试
- l 或 list: 查看当前代码段
- n 或 next: 执行下一行
- b 或 break: 打断点
例如: b 10 或 break 10 #在第10行打断点
- clear 1 # 删除编号为1的断点
- p 或 print: 打印变量
- s 或 step: 进入函数
- r 或 return: 从当前函数返回
作业:熟悉git,pdb操作
复习网络多线程服务器编程
tabase_names()
获得服务器上所有数据库列表
- 获取数据库对象: mydb = conn["test"]
conn: 数据库连接对象
- 获取集合对象: mycol = mydb["acct"]
mydb: 数据库对象
- 插入:
insert(), insert_one(), inser_many()
save()
- 修改:
update(query, update,
upsert=False, multi=False)
query: 筛选条件
update: 修改的内容
upsert: 是否执行插入
multi: 是否修改多行
- 删除: delete_one, delete_many
- 查询: find()
作业:
1)创建订单集合(名称orders),包含的域有:
order_id: 订单编号, 字符串
cust_name: 订单所属客户, 字符串
order_date: 下单时间,Date类型
status: 订单状态, 整数
order_detail: 订单明细, 文档数组
product_id: 商品编号, 字符串
product_name: 商品名称, 字符串
amt: 商品数量, 整数
price: 单价, 浮点数
2)插入3笔订单数据,每个订单至少包含1件商品
至少有一个订单包含多件商品(注意数据规范性)
db.orders.insert({
order_id:"201811200001",
cust_name:"Jerry",
order_date: new Date(),
status:1,
order_detail:[
{product_id: "P0001",
product_name:"水杯",
amt:1,
price:15.00
},
{product_id: "P0002",
product_name:"C语言编程",
amt:1,
price:65.00
}
]
})
db.orders.insert({
order_id:"201811200002",
cust_name:"Dokas",
order_date: new Date(),
status:1,
order_detail:[{
product_id: "P0003",
product_name:"手机",
amt:1,
price:1999.00
}]
})
3)编写下列语句
a)查找所有状态为1的订单
db.orders.find({status:1})
b)查找某个客户状态为1的订单(cust_name,status)
db.orders.find({
cust_name:"Jerry",
status:1
})
c)查找某个时间点以后下单的订单
db.orders.find({
order_date:{
$gt:ISODate("2018-11-20T08:29:45")}
})
d)统计订单笔数
db.orders.find().count()
e)修改某个订单的状态
db.orders.update(
{order_id:"201811200001"},
{$set:{status:2}})
f)为所有订单添加一个域:
支付状态(payment_status),整数
db.orders.update(
{},
{$set:{payment_status:null}},
false, true
)
g)查询所有订单中,商品编号为"P0001"的订单
db.orders.find({
"order_detail.product_id": "P0001"
})
h)在订单集合的订单编号(order_id)域上创建升序索引
db.orders.createIndex({order_id:1})
i)为某个订单增加备注信息(要求为字符串数组)
db.orders.update(
{order_id:"201811200001"},
{$pushAll:{remark:["工作日送达","后付款"]}}
)
j)删除一笔无效订单(status判断,具体值自己定)
7、Redis-数据库
8、Git-版本控制
Day05-Github
今天的内容
1. 版本管理工具git
1)什么是版本控制(Revision Control)
- 项目文档包含:
源码
文档(需求,设计,会议纪要,厂商联系方式)
软件包(开发工具,数据库,第三方库)
- 对各种软件所涉及到的文件进行管理
控制,变更记录,追溯
- 什么时候,什么人,修改了什么文件,什么内容
完整记录
配置管理岗: 专门进行配置管理
- 解决什么问题
- 版本管理规范性
- 解决版本更新,冲突
- 协调不同的开发者的变更,提高协同开发的效率
- 版本管理的相关术语
- 检出: 将软件配置(文件)从配置库中提取出来
- 检入: 将软件配置项(文件)放回配置库
- 主干版本: 标准配置库
- 分支版本: 为了某些特殊要求
和主干版本有差异的配置库
- 合并:
- A,B两个版本,将A的内容附加到B中
- A,B两个版本,A和B合并,形成新版本C
-历史记录:
文件变更的详细过程
-回滚:将配置退回到之前的某个状态
2) 版本管理方式
a)集中式管理
-配置库集中存放于中央服务器
-变更之前,先从中央服务器取得最新版本
然后进行变更,修改
-修改完成后,将变更提交到中央服务器
-缺点:集中式存放,必须联网,速度较慢
-典型工具:SVN
b)分布式
-没有中央服务器
-每个开发人员电脑都是一个完整配置库
-配置库位于本地,所以不一定需要联网
-每个开发者,可以将自己的代码贡献到
其他开发者仓库中
-典型工具:git
2.git: 分布式配置管理工具
1)更适合个人开发,管理配置库
2)分布式管理,不同svn的集中式管理
3)支持强大的分支功能
4)完整性优于svn
3.git安装:sudo apt-get install git
4.git配置
1)/etc/gitconfig文件:作用于系统所有用户
2)~/.gitconfig文件:用户目录下,作用于当前用户
3)工作目录下.git/config文件,作用于当前目录
优先级:工作目录>用户配置>系统配置
4)配置示例:
-git config --global user.name tarena
- git config --global user.email wangdb@tedu.cn
查看:cat ~/.gitconfig
- 查看已有配置: git config --list
5.git基本命令
1) init:
执行如下几个命令:
cd ~ # 进入用户主目录
mkdir gittest # 新建一个空目录
cd gittest
git init # 初始化,成功后当前会多出.git隐藏目录
2) add: 添加文件内容至索引
vim a.txt # 新建文本文件
git add a.txt # 将a.txt添加到仓库中
git status # 查看当前目录状态
3)commit: 提交变更至本地仓库
git commit 文件名 -m 注释信息
示例: git commit a.txt -m "create"
* 必须写注释
4)diff: 查看工作目录和仓库文件的差异
例如: git diff a.txt
5)reset: 版本的回滚
git reset --hard HEAD^ 回退到上一个版本
git reset --hard HEAD^^ 回退到上上一个版本
git reset --hard HEAD~n 回退到前面第n个版本
6. 分支管理
1)分支版本:有别于主版本,例如开发版,某个定制版
2)分支操作
- 查看所有分支: git branch
列出所有版本,带*表示当前所在分支
- 创建分支版本
git branch 分支版本名称
e.g.
git branch dev #创建名称为dev的分支版本
- 切换分支版本
git checkout 分支版本名称
e.g.
git checkout dev #切换到dev分支下
- 创建并切换分支
git checkout -b beta #创建并切换到beta分支下
- 版本合并:
git merge beta #把beta版本合并到当前分支
第一步: 进入到beta分支
git checkout beta
第二步: 修改a.txt,并提交(提交到beta分支)
第三步: 切换到dev分支
git checkout dev
第四步: 执行合并
git merge beta #把beta分支合并到当前分支
- 删除分支:
git branch -d beta
删除beta分支,如果没有合并则不允许删除
练习常用命令: init,add,commit,diff,checkout,log,status,reset
7. 标签管理
1)如果达到一个重要节点, 并希望永远记住那个提交
的快照, 可以使用标签
2)标签可以理解成一个指向某次提交的指针,
但不能移动
3)标签命令: git tag 标签名称.例如:
git tag v1.0 #将v1.0标签打到最新版本上
git tag #查看所有标签
git tag v0.9 0771ec3 #将v0.9标签打到制定的0771ec3版本上
git reset --hard v0.9 #退回到v0.9标签状态
8. github远程仓库
第一步:在gitee或github上注册账号
第二步:创建项目,并且拷贝地址
第三步:在工作目录下加入远程仓库地址
git remote add 名称 远程仓库地址
例如:
git remot add gitee https://gitee.com/bbsmil/git_test2.git
第四步:从远程仓库获取配置库
切换到master分支下,做一个pull操作
git pull 远程仓库名称 分支版本名称
例如: git pull gitee master
第五步: 修改工作目录文件,并且提交到本地仓库
例如: 修改a.txt后, 执行提交
git commit a.txt -m "remote test"
第六步: 推送到远程仓库
git push -u 远程仓库名称 分支版本
例如:git push -u gitee master
* 推送到gitee仓库的master分支下
9.调试工具
1)程序调试(debug): 程序在开发,测试,维护过程中
需要对程序测试,排除错误
2)调试工具:提高调试效率的工具
一般都能单步,打印变量,观察内部执行过程
3)pdb: Python自带的调试工具
4)使用:
- 启动调试: pdb3.5 tmp.py # 对tmp.py调试
- l 或 list: 查看当前代码段
- n 或 next: 执行下一行
- b 或 break: 打断点
例如: b 10 或 break 10 #在第10行打断点
- clear 1 # 删除编号为1的断点
- p 或 print: 打印变量
- s 或 step: 进入函数
- r 或 return: 从当前函数返回
作业:熟悉git,pdb操作
复习网络多线程服务器编程