【问题标题】:How to write a one function tool that does a check on a class variable in cherrypy如何编写一个功能工具来检查cherrypy中的类变量
【发布时间】:2015-04-07 18:25:30
【问题描述】:

我找不到让它工作的方法。我认为问题在于如何将类变量或类引用(self)传递给函数。代码类似如下:

def isconnected(classref):
    if not classref.serialObject:
        raise cherrypy.HTTPError("403 Forbidden")

cherrypy.tools.isconnected = cherrypy.Tool('before_handler', isconnected)

然后在app类中,应该这样使用:

class Controller(object):
    def __init__(self):
        self.serialObject = None

    @cherrypy.expose
    @cherrypy.tools.isconnected(self.serialObject)
    def serialVRead(self):
        # code here
        pass

换句话说,我基本上想在调用普通处理程序之前检查资源是否可用。另外,我需要它作为一个工具,因为我还有一些其他方法也想像这样装饰。

此外,我还想知道是否可以使用与引发 HTTPError 异常不同的解决方案来阻止正常处理程序执行。我尝试返回 True 或 False 但没有成功。

请让我知道这是否可行,或者是否有更好的方法来实现这一点。谢谢。

PD。我正在运行 Cherrypy 的最新版本(我认为是 3.3)

【问题讨论】:

    标签: python cherrypy


    【解决方案1】:

    1) 您可以像这样从cherrypy.serving.request.handler 检索当前处理程序所属的实例:

    #!/usr/bin/env python
    # -*- coding: utf-8 -*-
    
    
    import cherrypy
    
    
    config = {
      'global' : {
        'server.socket_host' : '127.0.0.1',
        'server.socket_port' : 8080,
        'server.thread_pool' : 8
      }
    }
    
    
    def isconnected():
      instance = cherrypy.serving.request.handler.callable.__self__
      if not instance.instanceAttr:
        raise cherrypy.HTTPError("403 Forbidden")
    
    cherrypy.tools.isconnected = cherrypy.Tool('before_handler', isconnected)
    
    
    class App:
    
      instanceAttr = None
    
    
      def __init__(self):
        self.instanceAttr = 123
    
      @cherrypy.tools.isconnected()
      @cherrypy.expose  
      def index(self):
        return '''foo'''
    
    
    if __name__ == '__main__':
      cherrypy.quickstart(App(), '/', config)
    

    2) 通常在 Python 中,装饰器在函数成为实例方法之前对其进行操作。如果您需要访问装饰器中的实例,您需要实现descriptor protocol(参见question about it)。因为 CherryPy 工具建立在装饰器之上,但有自己的工作流程,描述符机制可能无法工作。

    3) 有条件地避免正常处理程序使用cherrypy._cptools.HandlerTooldocswikiquestion with example)。

    【讨论】:

    • 很好的答案。信息量很大。我想我会用第一点和第三点来解决我的问题。谢谢!
    【解决方案2】:

    我认为您应该通过CherryPy Plugin 与串行对象进行交互,并与以下对象进行通信:

    serial_port = cherrypy.engine.publish('acquire_serial_port')
    

    插件的想法是跨请求共享资源、封装并可重用。

    您甚至可以将其混入仅引用串行插件已发布通道的工具中。

    【讨论】:

    • 我会调查一下,但这仍然不能解决我的问题。我需要在执行处理程序之前执行检查,并对其他一些不同的处理程序进行相同的检查。如何使用插件做到这一点?
    • 这些工具专门设计用于在处理程序之前或之后执行某些操作。查看有关扩展 CherryPy 的文档。 Tool + Plugin 是解决此类问题的正确解决方案。
    • 我知道这一点,并且已经非常彻底地阅读了文档。我现在的问题是,通过仅使用工具,在我当前的实现中,如何将类变量(self.serialObject)传递给装饰器。上面的代码当然不起作用,所以这个问题。
    猜你喜欢
    • 2018-01-24
    • 2013-05-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-05-21
    • 1970-01-01
    • 2015-04-16
    • 2020-12-25
    相关资源
    最近更新 更多