首页 > 解决方案 > Class::__del__:尝试在析构函数中使用成员对象释放资源失败

问题描述

我在Test下面有一个简单的类,它启动一个 Google Compute Engine VM,然后通过调用函数(显式)或依赖对象破坏(通过__del__隐式))来停止它。

class Test:
    def __init__(self):
        os.environ['GOOGLE_APPLICATION_CREDENTIALS'] = 'secret.json'
        self._compute = googleapiclient.discovery.build('compute',
                                                        'v1',
                                                        cache_discovery=False)
        print('starting vm')
        req = self._compute.instances().start(project='test-project',
                                              zone='us-east1-b',
                                              instance='test-vm',
                                              requestId=uuid.uuid1())
        self.execute(req)
        self._running = True

    def stop(self):
        print('stopping vm')
        req = self._compute.instances().stop(project='test-project',
                                             zone='us-east1-b',
                                             instance='test-vm',
                                             requestId=uuid.uuid1())
        self.execute(req)
        self._running = False

    def execute(self, req):
        print(f'method({req.methodId})')
        resp = req.execute()
        while resp['status'] != 'DONE':
            time.sleep(1)
            resp = req.execute()
        return resp

    def __del__(self):
        if self._running:
            print('stopping in destructor')
            self.stop()

该类Test的交互方式如下:

if __name__ == '__main__':
    print('start test')
    t = Test()

    print('vm running, wait 5 seconds')
    time.sleep(5)

    if len(sys.argv) == 2 and sys.argv[1] == 'stop':
        t.stop()

    print('test done')

当使用显式方法时(即:在对象开始被破坏t.stop() 之前调用),VM 停止正常:

$ ./test.py stop
start test
starting vm
method(compute.instances.start)
vm running, wait 5 seconds
stopping vm
method(compute.instances.stop)
test done

但是,当使用隐式方法时(即:依赖t超出范围并已Test::__del__调用),我从googleapiclient堆栈内抛出异常:

$ ./test.py 
start test
starting vm
method(compute.instances.start)
vm running, wait 5 seconds
test done
stopping in destructor
stopping vm
method(compute.instances.stop)
Exception ignored in: <bound method Test.__del__ of <__main__.Test object at 0x7fe091720320>>
Traceback (most recent call last):
  File "./test.py", line 46, in __del__
  File "./test.py", line 32, in stop
  File "./test.py", line 37, in execute
  File "/src/test/.venv/lib/python3.6/site-packages/googleapiclient/_helpers.py", line 130, in positional_wrapper
  File "/src/test/.venv/lib/python3.6/site-packages/googleapiclient/http.py", line 846, in execute
  File "/src/test/.venv/lib/python3.6/site-packages/googleapiclient/http.py", line 183, in _retry_request
  File "/src/test/.venv/lib/python3.6/site-packages/googleapiclient/http.py", line 164, in _retry_request
  File "/src/test/.venv/lib/python3.6/site-packages/google_auth_httplib2.py", line 198, in request
  File "/src/test/.venv/lib/python3.6/site-packages/httplib2/__init__.py", line 1926, in request
  File "/src/test/.venv/lib/python3.6/site-packages/httplib2/__init__.py", line 1595, in _request
  File "/src/test/.venv/lib/python3.6/site-packages/httplib2/__init__.py", line 1502, in _conn_request
  File "/usr/lib/python3.6/http/client.py", line 1239, in request
  File "/usr/lib/python3.6/http/client.py", line 1285, in _send_request
  File "/usr/lib/python3.6/http/client.py", line 1234, in endheaders
  File "/usr/lib/python3.6/http/client.py", line 1026, in _send_output
  File "/usr/lib/python3.6/http/client.py", line 986, in send
  File "/usr/lib/python3.6/ssl.py", line 975, in sendall
  File "/usr/lib/python3.6/ssl.py", line 944, in send
  File "/usr/lib/python3.6/ssl.py", line 642, in write
ssl.SSLError: Underlying socket connection gone (_ssl.c:2067)

问题:

标签: pythongoogle-api-python-client

解决方案


推荐阅读