【发布时间】:2018-06-18 01:08:41
【问题描述】:
我正在修改一些代码以在 Python 2 和 Python 3 之间兼容,但在单元测试输出中观察到警告。
/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/unittest/case.py:601:
ResourceWarning: unclosed socket.socket fd=4,
family=AddressFamily.AF_INET, type=SocketKind.SOCK_STREAM, proto=6,
laddr=('1.1.2.3', 65087), raddr=('5.8.13.21', 8080)
一项小型研究确定,requests 和 boto3 等流行库也发生了这种情况。
我可以完全忽略警告或filter it。如果是我的服务,我可以在回复中设置 connection: close 标头 (link)。
这是一个在Python 3.6.1 中显示警告的示例:
app.py
import requests
class Service(object):
def __init__(self):
self.session = requests.Session()
def get_info(self):
uri = 'http://api.stackexchange.com/2.2/info?site=stackoverflow'
response = self.session.get(uri)
if response.status_code == 200:
return response.json()
else:
response.raise_for_status()
def __del__(self):
self.session.close()
if __name__ == '__main__':
service = Service()
print(service.get_info())
test.py
import unittest
class TestService(unittest.TestCase):
def test_growing(self):
import app
service = app.Service()
res = service.get_info()
self.assertTrue(res['items'][0]['new_active_users'] > 1)
if __name__ == '__main__':
unittest.main()
是否有更好/正确的方法来管理会话,使其显式关闭,而不是依赖 __del__() 来产生这种警告。
感谢您的帮助。
【问题讨论】:
-
为你的类创建一个
close方法,委托给底层资源的close?更好的是,让你的类实现the context manager 协议,然后将它与with语句一起使用(__exit__可以调用你的close方法,而__enter__可以是一个微不足道的return self,所以它是没有太多额外的工作)。 -
不要使用 del 因为它不能保证在关闭时它会以正确的顺序被调用。这就是发明上下文管理器的原因。 @ShadowRanger 是正确的 - 添加 enter 和 exit 方法并使用 with 语法
-
在收到 DeprecationWarning 后出现此错误(我使用的是 assertEquals 而不是 assertEqual)。
标签: python python-3.x sockets python-unittest