1. IO多路复用
2. paramiko
3. MySQL
- SQL语句
- Python操作MySQL - pymysql模块
今日内容:
1. IO多路复用
- 监听多个socket变化
- socket服务端
IO多路复用 + socket 来实现Web服务器
a. 服务端优先运行
b. 浏览器: http://......
socket + send('协议..')
c. 获取客户端发来的url,根据URL不同响应数据
d. 断开链接
产出:
a. 浏览器发送数据:按照指定规则
b. 监听多个socket对象
c.
Web框架开发者
业务开发者
d. 模块独立化
#!/usr/bin/env python
# _*_ coding:utf-8 _*_
import select
import socket
sock = socket.socket()
sock.setblocking(False)
sock.bind(('127.0.0.1',8888))
sock.listen(5)
def process_data(client):
data = bytes()
while True:
try:
chunk = client.recv(1024)
except Exception as e:
chunk = None
if not chunk:
break
data += chunk
data_str = str(data,encoding='utf-8')
header,body = data_str.split('\r\n\r\n', 1)
header_list = header.split('\r\n')
header_dick = {}
for line in header_list:
value = line.split(":",1)
if len(value) == 2:
k,v = value
header_dick[k] = v
else:
header_dick['method'],header_dick['url'],header_dick['protocal'] = line.split(' ')
return header_dick,body
inputs = [sock,]
while True:
rlist,wlist,elist = select.select(inputs,[],[],0.05)
for client in rlist:
if client == sock:
conn,addr = client.accept()
conn.setblocking(False)
inputs.append(conn)
else:
header_dicy,body = process_data(client)
print(header_dicy)
request_url = header_dicy['url']
client.sendall(request_url.encode('utf-8'))
inputs.remove(client)
client.close()
http服务-函数
import select
import socket
class Http_server(object):
def __init__(self,routers):
self.routers = routers
def process_data(self,conn):
data = bytes()
while True:
try:
chunk = conn.recv(1024)
except Exception as e:
chunk = None
if not chunk:
break
data = data + chunk
data_str = str(data, encoding='utf-8')
header, body = data_str.split('\r\n\r\n', 1)
header_list = header.split('\r\n')
header_dict = {}
for line in header_list:
value = line.split(':', 1)
if len(value) == 2:
k, v = value
header_dict[k] = v
else:
header_dict['method'], header_dict['url'], header_dict['protcol'] = line.split(' ')
return header_dict, body
def run(self,host='127.0.0.1',port=8888):
sock = socket.socket()
# sock.setblocking(False)
sock.bind((host,port,))
sock.listen(5)
# while True:
# conn,addr = sock.accept() # 不在hang主,直接报错
# conn.setblocking(False)
# conn.recv(100) # 不在hang主,直接报错
inputs = [sock,]
while True:
# [1,]
rList,wList,eList = select.select(inputs,[],[],0.5)
for client in rList:
# 建立连接
if client == sock:
conn,addr = client.accept()
# conn.setblocking(False)
inputs.append(conn)
else:
header_dict,body = self.process_data(client)
# client.recv(1024)
request_url = header_dict['url']
# routers = [
# ('/index.html', f1),
# ('/login.html', f2)
# ]
func_name = None
for item in self.routers:
if item[0] == request_url:
func_name = item[1]
break
if not func_name:
client.sendall(b'404')
else:
result = func_name(header_dict,body)
client.sendall(result.encode('utf-8'))
inputs.remove(client)
client.close()
http服务-类
import Http
def f1(header_dict,body):
# ... Http...
# .....
return 'ffffff'
def f2(header_dict,body):
return 'aaaaaaaaaa'
routers = [
('/index.html',f1),
('/login.html',f2)
]
obj = Http.Http_server(routers)
obj.run()
http服务-类
参考博客:http://www.cnblogs.com/wupeiqi/p/6536518.html
- socket客户端(爬虫)
利用一个线程,同时发送n个请求(异步非阻塞模块)
url_list [
http://www.baidu.com,
http://www.baidu1.com,
http://www.baidu2.com,
http://www.baidu3.com,
]
import tornado.ioloop
import tornado.web
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/index.html", MainHandler),
])
if __name__ == "__main__":
application.listen(8889)
tornado.ioloop.IOLoop.instance().start()
程序员使用框架
a. 循环列表,为每一个URL生成Socket对象
b. 每一个socket对象,向远程发送链接请求
connect: 阻塞
c. 如果连接:
发送数据:遵循格式
d. 获取响应内容
e. 关闭
注意:可读和可写状态
import tornado.ioloop
import tornado.web
import socket
import select
sock = socket.socket()
sock.fileno()
class Foo(object):
def __init__(self,sock,callback,url,host):
self.sock = sock
self.callback = callback
self.url = url
self.host = host
def fileno(self):
return self.sock.fileno()
class NbIO(object):
def __init__(self):
self.fds = []
self.connections = []
def connect(self,url_list):
for item in url_list:
conn = socket.socket()
conn.setblocking(False)
# 1. 发送链接请求
try:
conn.connect((item['host'],80))
except BlockingIOError as e:
pass
obj = Foo(conn,item['callback'],item['url'],item['host'])
self.fds.append(obj)
self.connections.append(obj)
def send(self):
while True:
# wList,有对象;当前socket已经创建链接
try:
if len(self.fds) == 0:
return
rList,wList,eList = select.select(self.fds,self.connections,[],0.5)
# 【1,11】
for obj in rList:
# 4.有数据响应回来了
conn = obj.sock
data = bytes()
while True:
try:
d = conn.recv(1024)
data = data + d
except BlockingIOError as e:
d = None
if not d:
break
# print(data)
obj.callback(data) # 自定义操作 f1 f2
self.fds.remove(obj)
# print(len(self.fds),len(self.connections))
# 执行当前请求 函数:f1 f2
# 【1,2,3,】
for obj in wList:
# 2.已经连接上远程
conn = obj.sock
# 3. 发送数据
# HTTP/1.0\r\nHost: %s\r\n\r\n
template = "GET %s HTTP/1.1\r\nHost: %s\r\n\r\n" %(obj.url,obj.host,)
# template = "POST %s HTTP/1.1\r\nHost: 127.0.0.1:8888\r\n\r\nk1=v1&k2=v2" %(obj.url,)
conn.sendall(template.encode('utf-8'))
self.connections.remove(obj)
except OSError as e:
pass # 因为win下的select里的列表空了之后会报错,报错就忽视它
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write("Hello, world")
application = tornado.web.Application([
(r"/index.html", MainHandler),
])
if __name__ == "__main__":
application.listen(8889)
tornado.ioloop.IOLoop.instance().start()
异步IO模块
参考博客:http://www.cnblogs.com/wupeiqi/articles/6229292.html
产出:
1. setblockint(False)
2. select监听其他对象: def fileno():...
3. gevent,twisted,asycio ---> 单线程并发发送Http请求
2. Paramiko
参考博客:http://www.cnblogs.com/wupeiqi/articles/5095821.html
- 是一个模块,socket,SSH
- Python代码,实现远程服务器操作
功能:
a. 使用用户名密码:
- 命令 SSHClient -> Transport
- 文件 Transport
b. 使用用户名秘钥:
- 命令 SSHClient -> Transport
- 路径,也支持字符串形式
- 文件 Transport
====> SSH帮助类 <====
c.
执行创建session # 堡垒机 Bug
import paramiko
# 创建SSH对象
ssh = paramiko.SSHClient()
# 允许连接不在know_hosts文件中的主机
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
# 连接服务器
ssh.connect(hostname='192.168.12.59', port=22, username='root', password='sungaohui1990')
# 执行命令
stdin, stdout, stderr = ssh.exec_command('ls /')
# 获取命令结果
result = stdout.read()
print(result)
# 关闭连接
ssh.close()
paramiko使用
import paramiko
class SshHelper(object):
def __init__(self,host,port,username,pwd):
self.host = host
self.port = port
self.username = username
self.pwd = pwd
self.transport = None
def connect(self):
transport = paramiko.Transport((self.host, self.port,))
transport.connect(username=self.username, password=self.pwd)
self.transport = transport
def upload(self,local,target):
sftp = paramiko.SFTPClient.from_transport(self.transport)
# 将location.py 上传至服务器 /tmp/test.py
sftp.put(local, target)
# 将remove_path 下载到本地 local_path
# sftp.get('remove_path', 'local_path')
def cmd(self,shell):
ssh = paramiko.SSHClient()
ssh._transport = self.transport
stdin, stdout, stderr = ssh.exec_command(shell)
stdout.read()
def close(self):
self.transport.close()
if __name__ == '__main__':
obj = SshHelper('10.0.0.61','22','root','123456')
obj.connect()
obj.close()
paramikoHelper
产出:
- 链接远程,操作:命令,文件
3. MySQL
- 什么是MySQL
服务端:
a.socket服务端运行,监听:IP和端口
b.获取客户端发送的数据:
c.解析
d.去文件中做操作
客户端:
a.socket客户端:基于各种语言的客户端
b.验证
c.发送命令(学习规则SQL语句)
- 安装
服务端:
客户端:
- 基本使用:
a. 申请
用户:
授权:
用户名,数据库(文件夹),表(文件),增删改查,IP
b. 连接
mysql -u root -h c1.com -p
asdfasdf
mysql -u wupeiqi -h 192.168.12.111 -p 123
c. 规则
文件夹(数据库):
create database db1 default charset utf8;
drop database db1;
show databases;
use db1;
文件(表):
show tables;
create table tb1(
id int not null auto_increment primary key,
name char(20) null default 1,
age int not null)engine=innodb default charset utf8;
# 增
insert into tb1(name,age) values('alex',18);
# 删
delete from tb1 where id>1;
# 改
update tb1 set age=168 where id=2;
# 查
select * from tb1;
============================================================
外键:foreign key 一对多
create table deparment(
id int not null auto_increment primary key,
title char(32) null
)
create table person(
id int not null auto_increment primary key,
username char(32) null ,
age int not null,
deparment_id int not null,
constraint fk_cc foreign key (deparment_id) references deparment(id)
)
双向的外键: 多对多
create table deparment(
id int not null auto_increment primary key,
title char(32) null
)
create table host(
id int not null auto_increment primary key,
ip char(32) null,
port char(32) null
)
create table de_2_host(
id int not null auto_increment primary key,
did int not null,
hid int not null,
constraint fk_did_deparment foreign key (did) references deparment(id),
constraint fk_hid_host foreign key (hid) references host(id)
)
连表:
select * from person;
select * from person
left join deparment on person.deparment_id = deparment.id
#
1 alex 18 1 1 咨询
2 oldboy 68 3 3 基础
select id from deparment where title = "基础"
select hostid from host_deparment where deparment_id=1111
select * from host id in (1,2,3)
#######
4. pymysql
pip3 install pymysql
# 内部socket
import pymysql
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='', db='host_manage')
# cursor = conn.cursor()
cursor = conn.cursor(cursor=pymysql.cursors.DictCursor)
# 执行SQL,并返回受影响行数# 被搞...
effect_row = cursor.execute("select * from user",)
conn.commit()
ret = cursor.fetchall()
# ret = cursor.fetchmany(3)
# ret = cursor.fetchone()
# print(ret)
# ret = cursor.fetchone()
# print(ret)
cursor.close()
conn.close()
print(ret)
pymysql使用
import pymysql
# 创建连接
conn = pymysql.connect(host='127.0.0.1', port=3306, user='root', passwd='123', db='t1')
# 创建游标
cursor = conn.cursor()
username = input('请输入用户名:')
pwd = input('请输入密码:')
# 执行SQL,并返回受影响行数
#effect_row = cursor.execute("select * from userinfo where username=%s and pwd = %s", (username,pwd,))
# root or 1==1 --
# adfasdf
# sql = "select * from userinfo where username=%s and pwd = %s" %(username,pwd,)
# select * from userinfo where username=root or 1==1 -- and pwd = %s
#effect_row = cursor.execute(sql)
# 提交,不然无法保存新建或者修改的数据
conn.commit()
# 关闭游标
cursor.close()
# 关闭连接
conn.close()
pymysql使用