装饰器 (class) 对象何时被销毁?
When is a decorator (class) object destroyed?
我正在使用装饰器打开和关闭 neo4j 数据库会话(并允许我的装饰函数在该会话中 运行 查询)。起初我使用了装饰器函数:
from neo4j.v1 import GraphDatabase, basic_auth
def session(func,url="bolt://localhost:7474", user="neo4j",pwd="neo4j", *args, **kwargs):
def operate(*args, **kwargs):
driver = GraphDatabase.driver(url, auth=basic_auth(user,pwd))
session=driver.session()
kwargs["session"]=session
result=func(*args, **kwargs)
session.close()
return result
return operate
例如我调用这个函数:
@session
def RUN(command,session):
result=session.run(command)
return(result)
但是,这会为每个消耗资源的查询打开和关闭会话。因此,我尝试创建一个装饰器 class,并存储会话:
class session(object):
def __init__(self, func, url="bolt://localhost", user="neo4j", pwd="neo4j"):
try:
driver = GraphDatabase.driver(url, auth=basic_auth(user, pwd))
print("session opened")
except:
print("Exception during authentification")
self.__exit__()
else:
session=driver.session()
self.func=func
self.SESSION=session
def __call__(self, *args, **kwargs):
kwargs["session"]=self.SESSION
result=self.func(*args, **kwargs)
return result
def __del__(self):
print("del")
try:
self.SESSION.close()
print("session closed")
except:
print("could not close session")
这似乎可行,因为 "session opened" 只出现一次。但会话似乎没有关闭("session close" 从未打印)。
所以我的第一个问题是,如何在装饰器销毁时调用 self.SESSION.close() ?
我也想知道我是否理解我的代码在做什么。当我调用RUN
这样的装饰函数时,是否只创建了一个会话对象?如果我有另一个装饰函数怎么办 MATCH
@session
def MATCH(*args,**kwargs):
pass
会话对象是否相同?
如何
这是一个使用函数创建带有参数的装饰器的模板:
def decorator_maker(param1, param2):
print("The parameters of my decorator are: {0} and {1}".format(param1, param2))
def my_decorator(function_to_decorate):
def wrapper(arg1, arg2):
print("before call")
result = function_to_decorate(arg1, arg2)
print("after call")
return result
return wrapper
return my_decorator
用法如下:
@decorator_maker("hello", "How are you?")
def my_function(arg1, arg2):
print("The parameters of my function are: {0} and {1}".format(arg1, arg2))
return arg1 + "-" + arg2
有了class,就更直接了:
class decorator_maker(object):
def __init__(self, param1, param2):
print("The parameters of my decorator are: {0} and {1}".format(param1, param2))
self.param1 = param1
self.param2 = param2
def __call__(self, function_to_decorate):
def wrapper(arg1, arg2):
print("before call")
result = function_to_decorate(arg1, arg2)
print("after call")
return result
return wrapper
回答
要打开和关闭会话 before/after 函数调用,您必须在包装函数中实现它,如下所示:
class with_session(object):
def __init__(self, url="bolt://localhost", user="neo4j", pwd="neo4j"):
self.url = url
self.user = user
self.pwd = pwd
def __call__(self, f):
def wrapper(*args, **kwargs):
driver = GraphDatabase.driver(self.url, auth=basic_auth(self.user, self.pwd))
kwargs["session"] = session = driver.session()
try:
return f(*args, **kwargs)
finally:
session.close()
return wrapper
备注:
- 你可以让异常引发...
- 您应该重命名装饰器(就像我所做的那样)以避免隐藏名称 "session"。
- 这个装饰器不是上下文管理器。为此,您需要使用
__enter__
和 __exit__
,这是另一个用例...
参考
参见:How to make a chain of function decorators?
我正在使用装饰器打开和关闭 neo4j 数据库会话(并允许我的装饰函数在该会话中 运行 查询)。起初我使用了装饰器函数:
from neo4j.v1 import GraphDatabase, basic_auth
def session(func,url="bolt://localhost:7474", user="neo4j",pwd="neo4j", *args, **kwargs):
def operate(*args, **kwargs):
driver = GraphDatabase.driver(url, auth=basic_auth(user,pwd))
session=driver.session()
kwargs["session"]=session
result=func(*args, **kwargs)
session.close()
return result
return operate
例如我调用这个函数:
@session
def RUN(command,session):
result=session.run(command)
return(result)
但是,这会为每个消耗资源的查询打开和关闭会话。因此,我尝试创建一个装饰器 class,并存储会话:
class session(object):
def __init__(self, func, url="bolt://localhost", user="neo4j", pwd="neo4j"):
try:
driver = GraphDatabase.driver(url, auth=basic_auth(user, pwd))
print("session opened")
except:
print("Exception during authentification")
self.__exit__()
else:
session=driver.session()
self.func=func
self.SESSION=session
def __call__(self, *args, **kwargs):
kwargs["session"]=self.SESSION
result=self.func(*args, **kwargs)
return result
def __del__(self):
print("del")
try:
self.SESSION.close()
print("session closed")
except:
print("could not close session")
这似乎可行,因为 "session opened" 只出现一次。但会话似乎没有关闭("session close" 从未打印)。
所以我的第一个问题是,如何在装饰器销毁时调用 self.SESSION.close() ?
我也想知道我是否理解我的代码在做什么。当我调用RUN
这样的装饰函数时,是否只创建了一个会话对象?如果我有另一个装饰函数怎么办 MATCH
@session
def MATCH(*args,**kwargs):
pass
会话对象是否相同?
如何
这是一个使用函数创建带有参数的装饰器的模板:
def decorator_maker(param1, param2):
print("The parameters of my decorator are: {0} and {1}".format(param1, param2))
def my_decorator(function_to_decorate):
def wrapper(arg1, arg2):
print("before call")
result = function_to_decorate(arg1, arg2)
print("after call")
return result
return wrapper
return my_decorator
用法如下:
@decorator_maker("hello", "How are you?")
def my_function(arg1, arg2):
print("The parameters of my function are: {0} and {1}".format(arg1, arg2))
return arg1 + "-" + arg2
有了class,就更直接了:
class decorator_maker(object):
def __init__(self, param1, param2):
print("The parameters of my decorator are: {0} and {1}".format(param1, param2))
self.param1 = param1
self.param2 = param2
def __call__(self, function_to_decorate):
def wrapper(arg1, arg2):
print("before call")
result = function_to_decorate(arg1, arg2)
print("after call")
return result
return wrapper
回答
要打开和关闭会话 before/after 函数调用,您必须在包装函数中实现它,如下所示:
class with_session(object):
def __init__(self, url="bolt://localhost", user="neo4j", pwd="neo4j"):
self.url = url
self.user = user
self.pwd = pwd
def __call__(self, f):
def wrapper(*args, **kwargs):
driver = GraphDatabase.driver(self.url, auth=basic_auth(self.user, self.pwd))
kwargs["session"] = session = driver.session()
try:
return f(*args, **kwargs)
finally:
session.close()
return wrapper
备注:
- 你可以让异常引发...
- 您应该重命名装饰器(就像我所做的那样)以避免隐藏名称 "session"。
- 这个装饰器不是上下文管理器。为此,您需要使用
__enter__
和__exit__
,这是另一个用例...
参考
参见:How to make a chain of function decorators?