一、Python操作关系型数据库
1. SQL
SQL语句有两种类型:
- DDL(数据定义语言)
- 处理用户、数据库以及表单的创建、删除、约束和权限等
- DML(数据操作语言)
- 处理数据插入、选择、更新和删除
基本的SQL DDL
命令:
-- 创建数据库 CREATE DATABASE dbname
CREATE DATABASE d
-- 选择当前数据库 USE dbname
USE d
-- 删除数据库以及表单 DROP DATABASE dbname
DROP DATABASE d
-- 创建表 CREATE TABLE tbname(coldefs)
CREATE TABLE t(id INT, count INT)
-- 删除表 DROP TABLE tbname
DROP TABLE t
-- 删除表中所有的行 TRUNCATE TABLE tbname
TRUNCATE TABLE t
基本的SQL DML
命令:
-- 增加行 INSERT INTO tbname VALUES(...)
INSERT INTO t VALUES(7, 40)
-- 选择全部行和全部列 SELECT * FROM tbname
SELECT * FROM t
-- 选择全部行和部分列 SELECT cols FROM tbname
SELECT id, count FROM t
-- 选择部分行部分列 SELECT cols FROM tbname WHERE condition
SELECT id, count FROM t WHERE count > 5 AND id = 9
-- 修改一行的部分列 UPDATE tbname SET col=value WHERE condition
UPDATE t SET count=3 WHERE id=5
-- 删除部分行 DELETE FROM tbname WHERE condition
DELETE FROM t WHERE count <= 10 OR id = 16
2. DB-API
Python访问关系型数据库的标准API
# 连接数据库(包括用户名、密码、服务器地址...)
connect()
# 创建一个cursor对象来管理查询
cursor()
# 对数据库执行一个或多个SQL命令
excute()
# 等到excute之后的结果
fetchone()、fetchmane()、fetchall()
3. SQLite
import sqlite3
conn = sqlite3.connect('product.db')
curs = conn.cursor()
# 创建表
curs.execute('''
CREATE TABLE users (
id INTEGER PRIMARY KEY AUTOINCREMENT,
username TEXT NOT NULL,
password TEXT NOT NULL,
email TEXT
);
''')
# 插入数据(利用占位引用)
sql_insert = '''
INSERT INTO
users (username,password,email)
VALUES
(?, ?, ?);
'''
curs.execute(sql_insert, ('admin', '123456', 'admin@qq.com'))
# 更新数据
sql_update = '''
UPDATE
users
SET
email=?
WHERE
id=?;
'''
curs.execute(sql_update, ('1@qq.com', 0))
# 获取数据
sql_select = '''
SELECT
id, username, password, email
FROM
users;
'''
curs.execute(sql_select)
# 转换为python结构
rows = curs.fetchall()
print(rows)
# 删除数据
sql_delete = '''
DELETE FROM
users
WHERE
id=?;
'''
curs.execute(sql_delete, (0,))
# 提交
conn.commit()
# 关闭连接
conn.close()
4. SQLAlchemy
- 底层负责处理数据库连接池,执行SQL命令以及返回结果(与DB-API类似)
- 往上是SQL表达式语言,像Python的SQL生成器
- 高级的是对象关系映射(ORM),使用SQL表达式语言,将应用程序代码和关系型数据结构结合起来
安装pip install sqlalchemy
dialect + driver :// user : password @ host : port / dbname
import sqlalchemy as sa
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
# 连接数据库
conn = sa.create_engine('sqlite:///product.db')
# 进入ORM,定义类Product,并关联它的属性和表中的列
Base = declarative_base()
class Product(Base):
__tablename__ = 'product'
identity = sa.Column('identity', sa.String, primary_key=True)
count = sa.Column('count', sa.Integer)
money = sa.Column('money', sa.Float)
def __init__(self, identity, count, money):
self.identity = identity
self.count = count
self.money = money
def __repr__(self):
return '<Product({}, {}, {})>'.format(self.id, self.count, self.money)
# 创建数据库和表
Base.metadata.create_all(conn)
# 创建三个对象
first = Product('a', 1, 10)
second = Product('b', 2, 20)
third = Product('c', 3, 30)
# 创建连接到数据库的会话
Session = sessionmaker(bind=conn)
session = Session()
# 将创建的对象写入数据库
session.add(first)
session.add_all([second, third])
# 提交
session.commit()
5. Redis
安装 pip install redis
连接到redis服务器(确保电脑安装redis,并启动了redis服务器)
import redis
conn = redis.Redis('localhost', 6379)
conn.keys('*') # [...] 列出所有键
字符串:
# 设置值
conn.set('a', 'abcdefg') # True
conn.set('b', 2) # True
conn.set('c', 1.1) # True
conn.setnx('a', 'a') # False 键不存在时才设置
conn.mset({'a1': 1, 'a2': 2, 'a3': 3}) # True 一次设置多个键值
# 取值
conn.get('c') # b'1.1'
conn.getset('c', 1.2) # b'1.1' 返回旧值,同时设置新值
conn.mget(['a1', 'a2', 'a3']) # [b'1', b'2', b'3'] 一次取多个键的值
# 获取子串
conn.getrange('a', -2, -1) # b'fg'
# 替换子串(从指定位置开始替换,替换的子串有多长就替换多长)
conn.setrange('a', 0, 'AA') # 7
conn.get('a') # b'AAcdefg'
# 删除键
conn.delete('a') # True
# 递增递减(默认为1)
conn.incr('b') # 3
conn.incr('b', 10) # 13
conn.decr('b') # 12
conn.decr('b', 10) # 2
conn.incrbyfloat('c') # 2.2
conn.incrbyfloat('c', 0.5) # 2.7
conn.incrbyfloat('c', -1.0) # 1.7
列表(只能包含字符串):
# 插入(第一次插入时,列表被创建)
conn.lpush('alphabet', 'a') # 1 头部插入一项 [b'a']
conn.lpush('alphabet', 'b', 'c') # 3 头部插入多项 [b'c', b'b', b'a']
conn.linsert('alphabet', 'before', 'a', 'd') # 4 某个值之前插入 [b'c', b'b', b'd', b'a']
conn.linsert('alphabet', 'after', 'a', 'e') # 5 某个值之后插入 [b'c', b'b', b'd', b'a', b'e']
conn.rpush('alphabet', 'g') # 6 尾部插入 [b'c', b'b', b'd', b'a', b'e', b'g']
# 替换
conn.lset('alphabet', 2, 'f') # True 在索引处替换 [b'c', b'b', b'f', b'a', b'e', b'g']
# 检索
conn.lindex('alphabet', 2) # b'a' 取出对应索引的值
conn.lrange('alphabet', 0, 2) # [b'c', b'b', b'f'] 取出指定范围的值
conn.lrange('alphabet', 0, -1) # [b'c', b'b', b'f', b'a', b'e', b'g'] 取出全部
# 截取
conn.ltrim('alphabet', 1, 4) # True 仅保留指定范围的值 [b'b', b'f', b'a', b'e']
哈希表(只能包含字符串且只有一层结构,不能嵌套)
conn.hmset('song', {'a': 1, 'b': 2})
conn.hset('song', 'c', 3)
conn.hsetnx('song', 'a', 1.1) # 键不存在时才设置
conn.hget('song', 'c') # b'3'
conn.mget('song', 'a', 'b') # [b'1', b'2']
conn.hkeys('song') # [b'a', b'b', b'c'] 获取所有的键
conn.hvals('song') # [b'1', b'2', b'3'] 获取所有的值
conn.hlen('song') # 3 长度
conn.hgetall('song') # {b'a': b'1', b'b': b'2', b'c': b'3'}
集合:
conn.sadd('weeks', 'Mon', 'Tues', 'Wed') # 创建并添加
conn.scard('weeks') # 3 长度
conn.smembers('weeks') # {b'Tues', b'Mon', b'Wed'} 获取所有值
conn.srem('weeks', 'Wed') # 删除值
conn.sadd('single_weeks', 'Mon', 'Thur')
conn.sinter('weeks', 'single_weeks') # {b'Mon'} 返回交集
conn.sinterstore('i_weeks', 'weeks', 'single_weeks') # 交集存于新集合i_weeks
conn.sunion('weeks', 'single_weeks') # 并集
conn.sunionstore('u_weeks', 'weeks', 'single_weeks') # 并集存于u_weeks
conn.sdiff('weeks', 'single_weeks') # 差集
conn.sdiffstore('d_weeks', 'weeks', 'single_weeks') # 差集存于d_weeks
有序集合:
里面的值都是独一无二的,但是每一个值都关联对应的浮点值分数(score),可以通过值或者分数取得每一项
用途:
- 排行榜
- 二级索引
- 时间序列(把时间戳作为分数)
# 用时间戳跟踪用户的登陆
import time
now = time.time()
conn.zadd('logins', 'a', now)
conn.zadd('logins', 'b', now+(5*60))
conn.zadd('logins', 'c', now+(2*60*60))
conn.zadd('logins', 'd', now+(24*60*60))
conn.zrank('logins', 'c') # c登陆的次序
conn.zscore('logins', 'c') # 1521453722.9854615 登陆时间
conn.zrange('logins', 0, -1) # [b'a', b'b', b'c', b'd']
conn.zrange('logins', 0, -1, withscores=True)
# [(b'a', 1521446522.9854615), (b'b', 1521446822.9854615), (b'c', 1521453722.9854615), (b'd', 1521532922.9854615)]
位图:
# 跟踪用户的登录频率
# 每一天是一个单独的键,对应的用户ID设置位
days = ['2018-03-19', '2018-03-20', '2018-03-21']
user_1 = 1
user_2 = 2
user_3 = 3
# 第一天的访问
conn.setbit(days[0], user_1, 1)
conn.setbit(days[0], user_2, 1)
# 第二天的访问
conn.setbit(days[1], user_1, 1)
# 第三天的访问
conn.setbit(days[2], user_1, 1)
conn.setbit(days[2], user_3, 1)
# 统计这三天的日访客数
for day in days:
conn.bitcount(day) # 2, 1, 2
# 查看某一天某个用户是否访问
conn.getbit(days[1], user_2) # 0 没访问
# 有多少访客每天都会访问
conn.bitop('and', 'everyday', *days)
conn.bitcount('everyday') # 1
# 是否每天访问
conn.getbit('everyday', user_3)
# 这三天的独立访客数
conn.bitop('or', 'allday', *days)
conn.bitcount('allday') # 3
缓存和过期:
默认是永久的,设置5秒后过期:
conn.expire(key, 5)
二、文件和进程
1. 文件
file = 'oops.txt'
BASE_DIR = os.path.dirname(os.path.abspath(__file__))
file = os.path.join(BASE_DIR, 'test.txt')
file_copy = os.path.join(BASE_DIR, 'test_copt.txt')
file_rename = os.path.join(BASE_DIR, 'test_copy.txt')
# 打开或创建文件
with open(file, 'wt', encoding='utf-8') as fin:
fin.write('hello world')
# 检查文件或目录是否存在
import os
os.path.exists(file) # True
os.path.exists('.') # True 当前目录
os.path.exists('..') # True 上层目录
# 检查文件或目录
os.path.isfile(file)
os.path.isdir(file)
os.path.isabs(file) # 是否是绝对路径
# 复制文件
import shutil
shutil.copy(file, file_copy)
# 移动文件(删除源文件)
shutil.move(file, file_copy)
# 重命名
os.rename(file_copy, file_rename)
# 删除文件
os.remove(file_rename)
2. 目录
os.mkdir('poems') # 创建目录
os.rmdir('poems') # 删除目录(目录必须为空)
os.mkdir('poems/mcintyre') # 创建子目录
# 创建文件
with open('poems/mcintyre/main', 'wt', encoding='utf-8') as fin:
fin.write('hello world')
os.listdir('poems/mcintyre') # 列出目录内容
os.chdir('poems') # 调到另一个目录
glob列出匹配文件
-
*
匹配任意名称(类似于re中的.*
) -
?
匹配一个字符 - [abc] 匹配字符a, b, c
- [!abc] 匹配除a, b, c以外的所有字符
import glob
start_b = glob.glob('b*') # 所有以b开头的文件和目录
two_name = glob.glob('??') # 所有名称为两个字符的文件和目录
glob.glob('[klm]*e') # 所有以k,l或m开头并以e结尾的文件和目录
3. 进程
os.getpid() # 进程号
os.getcwd() # 当前目录
os.getuid() #only Unix 用户ID
os.getgid() #only Unix 用户组ID
import multiprocessing
import time
import os
def whoami(what):
print('进程 {} says: {}'.format(os.getpid(), what))
def do_this(what):
whoami(what)
if __name__ == "__main__":
whoami('我是主进程')
for n in range(1, 5):
p = multiprocessing.Process(target=do_this, args=('其他进程 {}'.format(n),))
p.start()
# p.terminate() # 终止进程
网友评论