【问题标题】:Connection decorator - how to pass values?连接装饰器 - 如何传递值?
【发布时间】:2017-10-16 14:12:29
【问题描述】:

首先,我正在研究这样的装饰器。基本上它是从主机到无线电模块槽服务的 ssh 隧道。 主机 radio_module(telnet)

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'给那里的参数,因为装饰器是在方法初始化之前创建的,对(这是我的第一个装饰器,我可能会说错。),比如:

serv_ip=self.serv.ip,

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

【问题讨论】:

  • 在调用嵌套函数 wrapper 之前,您不会获得实例 self - 此时它还将获得 connection。如果它与实例如此相关,我不确定装饰器是否适合您。
  • 我愿意接受建议。请提供更好的吗?

标签: python decorator python-decorators


【解决方案1】:

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

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

【讨论】:

  • 你,我喜欢这样。我非常喜欢那个! :D
  • @User007 谢谢。如果您需要,您可以“接受”答案。
  • 刚刚完成。我正在测试您的解决方案...效果与预期一样好。非常感谢您的帮助!
  • @User007 很高兴为您提供帮助。抱歉,我以为你不知道如何接受问题,因为你的个人资料似乎是新的。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-05-30
  • 1970-01-01
  • 2017-11-12
相关资源
最近更新 更多