连接装饰器 - 如何传递值?

时间:2017-10-16 14:12:30

标签: python decorator python-decorators

首先,我正在研究像这样的装饰器。基本上它是从主机到无线电模块通过serv的ssh隧道。 主机< - serv(ssh) - > radio_module(远程登录)

def connect(serv_ip, serv_port,
            serv_ssh_username,
            serv_ssh_password,
            radio_module_ip,
            radio_module_port=2323,
            host_ip='127.0.0.1',
            host_port=10022):
    def decorator(f):
        def wrapper():
            with SSHTunnelForwarder(
                    (serv_ip, int(serv_port)),
                    ssh_username=serv_ssh_username,
                    ssh_password=serv_ssh_password,
                    remote_bind_address=(radio_module_ip, int(radio_module_port)),
                    local_bind_address=(host_ip, int(host_port)),
                    # for debugging purposes:
                    # logger=create_logger(loglevel=1),
            ):
                with TelnetClient(host_ip, int(host_port)) as telnet:
                    f(telnet)
        return wrapper
    return decorator

现在,我希望建立这样的连接,做一些操作并关闭。因为我想对多种方法使用这样的模式,我想,装饰者应该做的工作,所以我已经准备好像... ...

from server import Server

class SystemModule(object):
    def __init__(self, server, username, password, hostname):
        self.server = server
        self.hostname = hostname
        self.username = username
        self.password = password

   @connect(
       serv_ip=???,
       serv_port=???,
       serv_ssh_username=???,
       serv_ssh_password=???,
       radio_module_ip=???,
   )
   def do_some_stuff(self, connection):
       #doing stuff

但是我不能给'self'参数,因为decorator是在初始化方法之前创建的,对(这是我的第一个装饰,我可能会说smth。错误),如:

serv_ip = self.serv.ip,

那么如何做到这一点呢?我希望将方法包装在一起,而不必每次都复制代码。提前感谢您的帮助

1 个答案:

答案 0 :(得分:3)

我建议改为使用上下文管理器:

from contextlib import contextmanager  
from server import Server

class SystemModule(object):
    def __init__(self, server, serv_ip, serv_port, username, password, hostname,
                 radio_module_ip, radio_module_port=2323, host_ip='127.0.0.1', host_port=10022):
        self.server = server
        self.hostname = hostname
        self.username = username
        self.password = password
        self.serv_ip = serv_ip
        self.serv_port = serv_port
        self.radio_module_ip = radio_module_ip
        self.radio_module_port = radio_module_port
        self.host_ip = host_ip
        self.host_port = host_port

   @contextmanager
   def connect():
        with SSHTunnelForwarder(
                (self.serv_ip, int(self.serv_port)),
                ssh_username=self.username,
                ssh_password=self.password,
                remote_bind_address=(self.radio_module_ip, int(self.radio_module_port)),
                local_bind_address=(self.host_ip, int(self.host_port)),
                # for debugging purposes:
                # logger=create_logger(loglevel=1),
        ):
            with TelnetClient(self.host_ip, int(self.host_port)) as telnet:
                yield telnet

   def do_some_stuff(self):
       with self.connect() as connection:
           #doing stuff with connection
           pass