python上下文操作linux
上下文管理
什么是上下文管理,在编程过程中,通常用来表示代码执行过程中的前后操作,例如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连接
# 需要先安装paramiko
import paramiko
ssh = 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()

浙公网安备 33010602011771号