Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/278.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
如何正确完成/清理pythonnet CLR对象?_Python_C#_Api_Code Cleanup_Python.net - Fatal编程技术网

如何正确完成/清理pythonnet CLR对象?

如何正确完成/清理pythonnet CLR对象?,python,c#,api,code-cleanup,python.net,Python,C#,Api,Code Cleanup,Python.net,我正在使用python通过提供的API与某个软件进行通信。由于API代码是用C#编写的,所以我使用pythonnet导入DLL并随后使用它。在优化代码时,使用Jupyter Lab或Jupyter Notebook这样做是有益的,因为您可以轻松比较代码和软件中的结果。但是,我遇到了清理问题。API要求您通过运行以下代码来建立连接 导入clr clr.AddReference('API') api=_u导入('api',globals(),locals(),[],0) connection=api

我正在使用python通过提供的API与某个软件进行通信。由于API代码是用C#编写的,所以我使用pythonnet导入DLL并随后使用它。在优化代码时,使用Jupyter Lab或Jupyter Notebook这样做是有益的,因为您可以轻松比较代码和软件中的结果。但是,我遇到了清理问题。API要求您通过运行以下代码来建立连接

导入clr
clr.AddReference('API')
api=_u导入('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
来实现,这在生成应用程序且尚未正确关闭时是正确的。该类类似于:

类APIWrapper:
定义初始化(self,api):
self.API=API
self.Connection=api.Connection()
def connect():
如果self.Connection.Alive:
raise RUNTIMERROR('运行时只允许一个活动应用程序')
app=self.Connection.connect()
返回应用程序
虽然这很好,但当我意外地做了以下事情时,我的问题就会出现:

wrap=APIWrapper()
wrap.connect()
执行此操作时,应用程序将启动,wrap.Connection.Alive的计算结果为True。但是,由于我没有将
wrap.connect()
的返回赋值给变量,因此无法使用
app.close()
关闭它。例如,如果我这样做:

wrap=APIWrapper()
打印(wrap.Connection.Alive)#->False
app=wrap.connect()
打印(wrap.Connection.Alive)#->True
app.close()
打印(wrap.Connection.Alive)#->False
wrap.connect()
打印(wrap.Connection.Alive)#->True

我不能再关闭连接了。我已经考虑过修改类,以便只将
wrap.connect()
绑定到
wrap.App
,并允许通过属性进行访问。这将解决丢失应用程序的问题,但我不希望为了代码可读性而不断调用wrap.app。此外,我只是想知道是否有一种适当的方法来处理这些终结问题?

首先,如果调用
wrap.connect()
而不将返回值存储在任何位置是问题所在,那么有一个简单的解决方案:不要这样做!看起来连接是一种资源,因此您必须跟踪它,以便在适当的时候释放它

在您的示例中,当有人再次调用
connect()
时,先前创建的连接会发生什么情况

其次,在Python中,有两种方法可以显式跟踪资源:

  • (强烈建议)。在这种情况下,您需要在包装器上实现一个上下文管理器
  • \uuuu del\uuu
    函数,您可以定义该函数,当不再需要对象时将调用该函数。您应该避免这种情况,因为它将在任意时间执行,这意味着当您尝试创建新连接时,旧连接可能仍然存在,因为Python还没有意识到它应该调用
    \uu del\uu

  • 另一种选择是制作。

    我同意我不应该这样做,我问这个问题的主要原因是我正在围绕API编写一个包装器,希望它尽可能健壮。通过这种方式,它允许与API动态交互,并确保在意外调用
    wrap.connect
    时不必重新启动任何东西。我还研究了
    \uu del\uu
    以及实现
    weakref.finalize
    <代码>\uuuu del\uuuu不起作用,因为clr中仍然存在连接,
    weakref.finalize()
    也不起作用。因此,我以不同的方式实现了它。(但我们将关注单身人士!)