Python 是否需要显式删除此对象?
我面临的问题是“CoreClient”的创建,它创建了一个到服务器的http请求。“with…as client”引入的当前代码可以确保在“client.annotate”完成后超出范围时客户端被销毁。然而,问题是,必须为每个处理“文本”的请求创建对象“客户端”。为了避免这种情况,我最好在init方法中创建对象:Python 是否需要显式删除此对象?,python,Python,我面临的问题是“CoreClient”的创建,它创建了一个到服务器的http请求。“with…as client”引入的当前代码可以确保在“client.annotate”完成后超出范围时客户端被销毁。然而,问题是,必须为每个处理“文本”的请求创建对象“客户端”。为了避免这种情况,我最好在init方法中创建对象: class Tokenizer() def __init__(self): self.name = 'MyTokenizer' self.tokenizer = Lang
class Tokenizer()
def __init__(self):
self.name = 'MyTokenizer'
self.tokenizer = Language.create_tokenizer(nlp)
def __call__(self, text):
if text:
with CoreClient(timeout=60000) as client:
doc = client.annotate(text, output_format='json')
else:
doc = Document("")
...
但是:
self.client = CoreClient(timeout=60000)
编辑:
为了更清楚,我添加了方法enter的实现。它似乎只是返回对象“self”。在本例中,我不担心它,因为当引用计数变为零时,Python将处理它。而且,
del
实际上并不删除和删除对象。可能是,但可能不是del
将减少对象的引用计数
以此为例:
def __enter__(self):
self.start()
return self
def start(self):
if self.start_cmd:
if self.be_quiet:
# Issue #26: subprocess.DEVNULL isn't supported in python 2.7.
stderr = open(os.devnull, 'w')
else:
stderr = self.stderr
print(f"Starting server with command: {' '.join(self.start_cmd)}")
self.server = subprocess.Popen(self.start_cmd,
stderr=stderr,
stdout=stderr)
这就是为什么我认为应该让Python来处理对象的破坏。Python跟踪对象引用计数,并知道何时不再需要它们。因此,让它为您处理这些事情。您只需要创建一次
CoreClient的实例。with
语句只确保在with
语句体前后调用该实例的\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和方法;您不需要每次都创建一个新实例
In [1]: class Test:
...: def __del__(self):
...: print('deleted')
...:
In [2]: t = Test()
In [3]: del t
deleted
In [4]: t = Test()
In [5]: t1 = t
In [6]: del t # Nothing gets printed here because t1 still exists
In [7]: del t1 # reference count goes to 0 and now gets printed
deleted
每次将CoreClient
实例用作上下文管理器时,\uuuuuuuuuuuuuuuuuuuuuuuuuuuu>和\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu
当收集标记器
实例时,将收集客户端。但是,除非您处于活动的with
语句中,否则CoreClient
实例不会执行任何操作。为什么不让python的默认处理来处理这个问题呢?每当调用对象的析构函数时,对象都将被销毁。如果del
对象,则只是删除对它的引用。如果仍然存在对该对象的其他引用,则该对象仍将保留。我认为当前创建该对象的方式很好,除非由于某种原因,CoreClient
限制了它可以拥有的实例数。@Chrispresso IOW,del
不会删除对象,要回答标题中的问题,几乎不需要使用del
。对于您当前的代码,它就是。问题是,是否需要这样做?我的建议创建一次CoreClient
实例,但调用CoreClient.\uuu在该实例上输入\uuuuuu
,每次调用标记器
实例。\uu del\uuuu
也可能永远不会被调用,如果对象超出范围的原因是解释器正在关闭。我主要关心的是每个请求,创建CoreClint将花费太多时间,这是不好的。应该创建一次。嗨,切普纳:不幸的是,我刚刚测试并发现,由于调用函数中的语句“with self.client”,CoreClient被一次又一次地创建,这使得系统非常慢,因为系统的初始化需要时间。如果删除“with self.client”,则系统只初始化一次。但是在这种情况下,系统不会在完成http请求后关闭它,对吗?准确地说,CoreClient
不是一次又一次地创建的;您创建了一次,但是\uuuuu enter\uuuu
方法确实从头开始启动了一个新服务器。如果要跨调用使用同一台服务器,则必须重新实现CoreClient
的工作方式。基本上,如何避免系统以当前代码形式多次初始化?根据您所展示的内容,似乎唯一的方法是重写CoreClient
,除非有办法在CoreClient中启动服务器。请将self.start\u cmd
设置为None
。
In [1]: class Test:
...: def __del__(self):
...: print('deleted')
...:
In [2]: t = Test()
In [3]: del t
deleted
In [4]: t = Test()
In [5]: t1 = t
In [6]: del t # Nothing gets printed here because t1 still exists
In [7]: del t1 # reference count goes to 0 and now gets printed
deleted
class Tokenizer()
def __init__(self):
self.name = 'MyTokenizer'
self.tokenizer = Language.create_tokenizer(nlp)
self.client = CoreClient(timeout=60000) # Create client here
def __call__(self, text):
if text:
with self.client:
doc = self.client.annotate(text, output_format='json')
else:
doc = Document("")