所谓上下文管理器即在一个类中重写了__enter__方法和__exit__方法的类就可以成为上下文管理器类.
我们可以通过 with 语句结合上下文管理器简化一些操作.
使用 with 语句结合自定义上下文管理器完成数据库相应的操作, 代码实现如下:
- # 1. 导入模块
- import pymysql
- # 创建自定义上下文管理器对象
- class MyDatabase(object):
- # 接收参数并创建数据库连接对象
- def __init__(self, host, port, user, passwd, database):
- self.__db = pymysql.Connection(host, port, user, passwd, database, charset='utf8')
- # 返回数据库连接对象
- def __enter__(self):
- return self.__db
- # 关闭数据库连接
- def __exit__(self, exc_type, exc_val, exc_tb):
- self.__db.close()
- def main():
- # 使用 with 关键字接收 enter 返回的对象给 db
- with MyDatabase('localhost', 3306, 'root', 'mysql', 'JDDB') as db:
- # 利用 db 创建游标
- cur = db.cursor()
- sql = '''select * from %s'''
- cur.execute(sql, (goods,))
- result = cur.fetchall()
- for i in result:
- print(i)
- # 关闭游标
- cur.close()
- # 程序入口
- if __name__ == '__main__':
- main()
上下文管理器类的代码流程:
1. 编写__init__方法用来接收参数, 并创建数据库连接对象;
2. 重写__enter__方法, 返回数据库连接对象;
3. 重写__exit__方法, 用来关闭数据库连接;
with 语句代码流程:
1. 当将创建对象的语句放到 with 语句里时不会创建对象, 而是接受__enter__方法返回的对象并给对象起个别名;
2. 使用接受到的对象即数据库连接对象, 创建游标;
3. 编写 SQL 语句, 并通过游标执行 SQL 语句;
4. 获取 SQL 语句的查询结果, 并显示出来;
5. 关闭游标;
6. 当 with 语句内的代码执行完毕后自动执行__exit__方法关闭数据库连接.
利用 with 结合自定义上下文类实现 HTTP 服务端:
- # 1. 导入 socket 模块
- import socket
- class MySocket(object):
- # 2. 编写 init 方法接收 port 参数
- def __init__(self, port):
- self.__port = port
- # 3. 创建 socket 对象
- self.__sk = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- # 4. 编写 enter 方法返回套接字对象
- def __enter__(self):
- # 设置端口复用
- self.__sk.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
- # 绑定端口
- self.__sk.bind(self.__port)
- # 设置端口监听
- self.__sk.listen(128)
- # 返回套接字对象
- return self.__sk
- # 5. 编写 exit 方法关闭套接字对象
- def __exit__(self, exc_type, exc_val, exc_tb):
- self.__sk.close()
- def main():
- # 使用 with 关键字 并接受返回的套接字对象给 sk
- with MySocket(8000) as sk:
- # 等待客户端连接
- clicent, ip_port = sk.accept()
- recv_data = clicent.recv(1024)
- print(recv_data.decode('utf-8'))
- # 编写 HTTP 响应报文
- http_line = 'HTTP/1.1 GET 200 OK\r\n'
- http_header = 'Server PWS/1.0\r\n'
- http_body = 'Welcome to index!\r\n'
- send_data = (http_line + http_header + '\r\n' + http_body).encode('utf-8')
- clicent.send(send_data)
- # 关闭客户端连接
- clicent.close()
- # 编写程序入口
- if __name__ == '__main__':
- main()
自定义上下文管理器类的代码解读:
1. 编写__init__方法, 用来接收参数并创建套接字对象;
2. 编写__enter__方法, 并使用套接字对象设置端口复用, 绑定端口, 并设置监听, 然后返回套接字对象;
3. 编写__exit__方法, 关闭套接字对象.
with 语句代码解读:
1. 接收 enter 返回的套接字对象, 并起个别名,
2. 通过返回套接字对象等待客户端连接,
3. 接收客户端连接成功后会返回一个新的套接字和 IP 端口号,
4. 使用客户端套接字发送 HTTP 响应报文
5. 关闭客户端连接
6. 当 with 语句中的代码执行完毕后自动执行__exit__方法, 关闭服务器连接
来源: https://www.cnblogs.com/chao666/p/12059950.html