Python 里面的装饰器 class
Python Decorator inside class
我有一个 class 基本上连接到 SFTP 服务器,与问题不太相关。
我正在尝试创建一个包装器 function/decorator 来帮助我消除大量重复代码。
这是一段代码的工作版本:
def upload_file(self, local_file, destionation_path: str):
with pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
) as sftp:
local_file_path = local_file
print(f'Uploading output file: {local_file_path} to remote location: {destionation_path}')
sftp.put(
localpath=local_file_path,
remotepath=destionation_path,
confirm=False
)
我宁愿不必在每个函数的开头都写上 `with pysftp.... as sftp' 部分。
我试着这样解决问题:
def connection(self, function):
def wrapper(*args, **kwargs):
connection = pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
)
return_val = function(connection, *args, **kwargs)
return return_val
return wrapper
@connection
def upload_file(self, connection, local_file, destionation_path: str):
print(f'Uploading output file: {local_file} to remote location: {destionation_path}')
connection.put(
localpath=local_file,
remotepath=destionation_path,
confirm=False
)
但是话又说回来,如果它是这样声明的,则不能将 self 参数传递给包装器,我如何从其他地方调用 upload_file?由于连接参数是由装饰器实例化的。
如果这应该以任何其他方式完成,我将非常感谢一些指南,因为我什至不确定我在寻找什么。
self
应该作为 wrapper
函数中的参数:
def connection(function):
def wrapper(self, *args, **kwargs):
with pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
) as connection:
return_val = function(connection, *args, **kwargs)
return return_val
return wrapper
无论如何,您可以像@pqans 所说的那样将连接传递给构造函数。这是最简单的解决方案,也是我会做的。我觉得你有点复杂。
使用上下文管理器在运行时注入依赖:
with pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
) as connection:
sftp = MyClass(connection)
sftp.upload_file(local_file, destionation_path)
另一种方法是为您的 class 创建上下文管理器并使用依赖注入模式:
class ContextWrapperClass(object):
def __init__(self, my_ftp_class_instance, *args, **kwargs):
# ... Some code here
self.ftp_operations = my_ftp_class_instance # This could be an instance
def __enter__(self):
self.connection = pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
)
self.ftp_operations.connection = self.connection
return self.ftp_operations
def __exit__(self, type, value, traceback):
print("Exception has been handled")
self.connection.close()
return True
那么您可以将其用作:
with ContextWrapperClass(MyClass()) as sftp:
# connection is inserted as dependency injection on constructor
sftp.upload_file(local_file, destionation_path)
我有一个 class 基本上连接到 SFTP 服务器,与问题不太相关。 我正在尝试创建一个包装器 function/decorator 来帮助我消除大量重复代码。 这是一段代码的工作版本:
def upload_file(self, local_file, destionation_path: str):
with pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
) as sftp:
local_file_path = local_file
print(f'Uploading output file: {local_file_path} to remote location: {destionation_path}')
sftp.put(
localpath=local_file_path,
remotepath=destionation_path,
confirm=False
)
我宁愿不必在每个函数的开头都写上 `with pysftp.... as sftp' 部分。 我试着这样解决问题:
def connection(self, function):
def wrapper(*args, **kwargs):
connection = pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
)
return_val = function(connection, *args, **kwargs)
return return_val
return wrapper
@connection
def upload_file(self, connection, local_file, destionation_path: str):
print(f'Uploading output file: {local_file} to remote location: {destionation_path}')
connection.put(
localpath=local_file,
remotepath=destionation_path,
confirm=False
)
但是话又说回来,如果它是这样声明的,则不能将 self 参数传递给包装器,我如何从其他地方调用 upload_file?由于连接参数是由装饰器实例化的。 如果这应该以任何其他方式完成,我将非常感谢一些指南,因为我什至不确定我在寻找什么。
self
应该作为 wrapper
函数中的参数:
def connection(function):
def wrapper(self, *args, **kwargs):
with pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
) as connection:
return_val = function(connection, *args, **kwargs)
return return_val
return wrapper
无论如何,您可以像@pqans 所说的那样将连接传递给构造函数。这是最简单的解决方案,也是我会做的。我觉得你有点复杂。
使用上下文管理器在运行时注入依赖:
with pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
) as connection:
sftp = MyClass(connection)
sftp.upload_file(local_file, destionation_path)
另一种方法是为您的 class 创建上下文管理器并使用依赖注入模式:
class ContextWrapperClass(object):
def __init__(self, my_ftp_class_instance, *args, **kwargs):
# ... Some code here
self.ftp_operations = my_ftp_class_instance # This could be an instance
def __enter__(self):
self.connection = pysftp.Connection(
host=self.host,
username=self.username,
password=self.password,
cnopts=self.cnopts
)
self.ftp_operations.connection = self.connection
return self.ftp_operations
def __exit__(self, type, value, traceback):
print("Exception has been handled")
self.connection.close()
return True
那么您可以将其用作:
with ContextWrapperClass(MyClass()) as sftp:
# connection is inserted as dependency injection on constructor
sftp.upload_file(local_file, destionation_path)