python - 如何正确完成/清理 pythonnet CLR 对象?
问题描述
我正在使用 python 通过提供的 API 与某个软件进行通信。由于 API 代码是用 C# 编写的,我使用 pythonnet 导入 DLL 并随后使用它。在优化代码时使用例如 Jupyter Lab 或 Jupyter Notebook 这样做是有益的,因为您可以轻松地比较代码和软件中的结果。但是,我遇到了清理问题。API 要求您通过运行以下代码来建立连接
import clr
clr.AddReference('API')
api = __import__('API', globals(), locals(), [], 0)
connection = api.connection()
app = connection.connect()
现在您可以使用app
. 我的问题的主要原因是您只能在 CLR 中拥有一个应用程序。如果你想创建一个新的,你应该调用app.close()
和 随后newapp = connection.connect()
。没有明确定义当您创建newapp
而不调用时会发生什么。app.close()
我不确定 C# 将如何处理这个问题,它会覆盖app
内存中的内存,app
现在还会指向newapp
,还是其他什么?有了这个,我更加不确定 python+CLR 是如何处理它的。
为了确保您始终使用正确连接的应用程序,我创建了一个只允许app
存在一个实例的类。此限制是通过 API 评估来实现connection.Alive
的,当应用程序已生成但尚未正确关闭时,该 API 为 True。该类类似于:
class APIWrapper:
def __init__(self, api):
self.API = api
self.Connection = api.connection()
def connect():
if self.Connection.Alive:
raise RunTimeError('Only one live application is allowed at runtime')
app = self.Connection.connect()
return app
虽然这很好用,但当我不小心做了类似的事情时,我的问题就出现了:
wrap = APIWrapper()
wrap.connect()
这样做时,应用程序上线并且 wrap.Connection.Alive 评估为 True。但是,由于我没有将返回值分配给wrap.connect()
变量,因此无法使用app.close()
. 例如,如果我这样做:
wrap = APIWrapper()
print(wrap.Connection.Alive) # -> False
app = wrap.connect()
print(wrap.Connection.Alive) # -> True
app.close()
print(wrap.Connection.Alive) # -> False
wrap.connect()
print(wrap.Connection.Alive) # -> True
我不能再关闭连接了。我考虑过改变类,以便只绑定wrap.connect()
到wrap.App
并允许通过属性进行访问。这将解决丢失应用程序的问题,但我宁愿不必为了代码可读性而连续调用 wrap.App。另外,我只是想知道是否有适当的方法来处理这些最终确定问题?
解决方案
首先,如果调用wrap.connect()
时没有在任何地方存储返回值是问题所在,那么有一个简单的解决方案:不要这样做!看起来连接是一种资源,因此您必须跟踪它以在时机成熟时正确释放它。
在您的示例中,当有人connect()
再次调用时,先前创建的连接会发生什么?
其次,在 Python 中有两种方法可以显式地跟踪资源:
with
语句 + 上下文管理器(强烈推荐)。在这种情况下,您需要在包装器上实现上下文管理器。__del__
您可以定义的函数,它将在不再需要对象时调用。这个你应该避免,因为它会在任意时间执行,这意味着当你尝试创建一个新的连接时,旧的连接可能仍然存在,因为 Python 还没有意识到它应该调用它__del__
。
另一种选择是制作一个单例。
推荐阅读
- ios - 导航控制器 segue 以模态方式呈现
- c# - 搜索让给线程池的 Task.Yield 等效项
- android - 显示在颤振应用程序中的图像帧上运行 tflite 的相机活动
- applescript - 使用 AppleScript 在系统偏好设置中取消选中 HDR
- python - Python正则表达式匹配多行字符串
- python - 将 JSON 文件转换为具有多值特征的 CSV 文件
- java - .ignoring 如何融入 Selenium Webdriver Fluent Waits 流程?
- python - 如何自动创建字典以写入 csv 文件-Python
- php - 帖子上的后备图片
- oauth-2.0 - 如何在启用 ADFS 的 OAuth 中为授权码授予生成令牌