C++内存管理:简易内存池的实现
912 2023-04-03 04:27:20
什么是上下文管理,在编程过程中,通常用来表示代码执行过程中的前后操作,例如open函数,在操作文件之前,需要打开文件,然后再对文件进行读写操作,操作结束后,需要关闭文件。
上下文管理的作用场景:文件操作、网络的连接与断开,数据库连接操作及断开等。
示例
我们在使用open函数对文件操作时,是这样实现的#获取文件对象fp = open('info','a+')#对文件的操作#操作接收后,关闭文件流fp.close()
上面的方法,虽然可以实现文件的读写操作,但是如果文件的操作过程中,发生了异常,会导致fp.close()不会执行。
#获取文件对象try:fp = open('info','a+')#对文件的操作except:print('这里发生了异常')#操作接收后,关闭文件流finally:fp.close()
通过这种方式,添加异常处理,使用finally老保证不管是否发生异常,都执行关闭文件操作,以确保文件的正常关闭。
上述方法虽然能解决这个问题,但是实现过程中,需要做出对应的异常处理,比较麻烦。
所以我们可以使用with语法来实现,with实际上就是上下文的管理。
with open('info','a+') as fp:#文件操作
with时如何实现上下文管理的,如何编写一个自己的上下文管理呢
在python中,如果一个类,实现了__enter__()方法和__exit__()方法,那么这个类就可以是一个上下文管理器。
__enter__():用来表示上文管理,需要返回一个操作对象
__exit__():执行结束后的方法,不管过程中是否发生异常,这里都会执行,也是with中执行结束后的操作
实例
class File: def __init__(self): print('执行构造方法') def __enter__(self): print('进入方法') def __exit__(self, exc_type, exc_val, exc_tb): print('执行结束方法')with File() as f: print('执行操作')
执行结果
执行构造方法进入方法执行操作执行结束方法
执行过程是先创建一个File类的对象,并命名为f,实例化时,调用了init方法,所以输出“执行构造方法”,然后再调用enter方法,输出“进入方法”。在执行with下的子句,即用户的操作方法。
通过上下文操作mysql数据库
# 封装的类是可以提供方法的,但是需要考虑异常处理问题# 还要考虑如何确保链接的关闭class Mysql(object): def __init__(self,**kwargs): self.conn = pymysql.connect(**kwargs) self.cursor = self.conn.cursor() def execsql(self,sql): self.cursor.execute(sql) return self.cursor.fetchall() def fetch(self,n=1): return self.cursor.fetchmany(n) def close(self): self.cursor.close() self.conn.close()class Mysql_with(object): # 通过构造方法实现数据库连接的创建 def __init__(self,**kwargs): self.conn = pymysql.connect(**kwargs) # 获取游标对象 self.cursor = self.conn.cursor() def __enter__(self): # 返回一个游标对象 return self.cursor def __exit__(self, exc_type, exc_val, exc_tb): self.cursor.close() self.conn.close()with Mysql_with(host='192.168.2.99',port=3306,user='root',passwd='',db='mysql') as mysql: # mysql是什么,mysql接收的是__enter__方法返回的结果。所以mysql是cursor mysql.execute('select user,host from user;') print(mysql.fetchall())
上下文操作linux
class Linux: def __init__(self,host='',user='',password='',port=22): self.host = host self.user = user self.password = password self.port = port # 初始化ftp self.ftp = '' # 初始化ssh self.ssh = ''class SSH_Linux(Linux): def __enter__(self): # self.__ssh() return self def command(self,comd): # 调用ssh连接,创建连接 try: self.__ssh() except AuthenticationException: return '登录错误' except TimeoutError: return '连接失败,请检查服务器地址是否正确' stdin,stdout,stderr = self.ssh.exec_command(comd) # 处理命令的执行结果,并返回 return str(stdout.read(),encoding='utf-8') def __ssh(self): #创建ssh连接 self.ssh = paramiko.SSHClient() try: self.ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy()) self.ssh.connect(hostname=self.host,username=self.user,password=self.password,port=self.port) except AuthenticationException: raise AuthenticationException except TimeoutError: raise TimeoutError def __exit__(self, exc_type, exc_val, exc_tb): self.ssh.close()class FTP_Linux(Linux): def __enter__(self): return self def __ftp(self): # 创建ftp连接 self.transport = paramiko.Transport((self.host,self.port)) try: self.transport.connect(username=self.user,password=self.password) except AuthenticationException: raise AuthenticationException self.ftp = paramiko.SFTPClient.from_transport(self.transport) def get(self,source,dept): try: self.__ftp() except AuthenticationException: return '登录错误' # 处理没有找到要下载的文件问题 try: # 判断dest是否是一个文件 if os.path.isfile(dept): self.ftp.get(source,dept) elif os.path.isdir(dept): # 读取到要下载的文件的文件名 file = os.path.basename(source) # 将文件名和下载路径拼接 file_name = os.path.join(dept,file) self.get(source,file_name) elif not os.path.exists(dept): self.ftp.get(source,dept) except FileNotFoundError: return '要下载的目标文件不存在' def put(self,source,dept): try: self.__ftp() except AuthenticationException: return '登录错误' # 检查要上传的文件是否存在 if os.path.isfile(source): self.ftp.put(source,dept) else: return '上传必须是已存在的文件' def __exit__(self, exc_type, exc_val, exc_tb): self.ftp.close() self.transport.close()# ssh = Linux('192.168.2.16',user='root',password='123456')# with SSH_Linux('192.168.2.16',user='root',password='123456') as ssh:# print(ssh.command('ls'))with FTP_Linux('192.168.2.16',user='root',password='123456') as ftp: ftp.get('/home/test','.')
如果对于python访问linux系统不是很熟悉的话,可以参考下面的demo
linux ssh连接
# 需要先安装paramikoimport paramikossh = paramiko.SSHClient()ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())ssh.connect('192.168.2.16',username='root',password='123456')stoin,out,err = ssh.exec_command('ls')# stoin标准输入,执行时,不关心。# out:标准输出流。用来接收命令执行的结果的# err:标准错误,用来接收命令执行失败的错误信息# 标准输出流返回的是一个二进制对象,所以需要转成字符串对象,需要用utf8编码print(str(out.read(),encoding='utf-8'))ssh.close()
linux文件上传下载
#coding=utf-8__author__ = 'jia'import paramiko#Transportj接收一个socker对象,也就是ip地址和端口,因为只有一个参数,所以将两个参数# 以元组的形式传入transport = paramiko.Transport(('192.168.2.16',22))# 创建连接transport.connect(username='root',password='123456')# 创建ftp连接(通过socker创建ftp连接)ftp = paramiko.SFTPClient.from_transport(transport)# 上传文件ftp.put('test.html','/home/test.html')# 下载文件ftp.get('/etc/passwd','D:\\password')# 关闭ftp连接ftp.close()# 关闭socker连接transport.close()