Я использую 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
. Это ограничение реализовано путем оценки connection.Alive
через API, что является истинным, когда приложение создано и еще не закрыто должным образом. Класс похож на:
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 постоянно для удобочитаемости кода. Кроме того, мне просто интересно, есть ли правильный способ решения этих проблем с завершением?