2014-10-25 3 views
13

Python 3.2 представил ResourceWarning для незакрытых системных ресурсов (сетевые сокеты, файлы):Отключение Python 3.2 ResourceWarning

Хотя код работает чистым в производстве, я получаю много следующих предупреждений при выполнении модульных тестов за счет использования сторонних библиотек, где появляется предупреждение. Я мог бы исправить библиотеку, но, с другой стороны, было намного проще просто игнорировать ее во время тестового прогона.

block_io-python/block_io/__init__.py:182: ResourceWarning: unclosed <ssl.SSLSocket fd=11, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=6, laddr=('x', 58395), raddr=('x, 443)> 

Каким образом можно отключить эти предупреждения? Я пробовал следующее, но никакого эффекта:

warnings.filterwarnings("ignore", category=ResourceWarning) 

(Запускать во время времени испытания единицы измерения).

+3

Может быть, мне позволено, если очевидное поведение не работает, и я не знаю, что я делаю неправильно? :) –

+0

Может быть, модуль, выдающий предупреждение, использует 'warnings.showwarning'. Кажется, что функция обходит предупреждающий фильтр. – Dunes

+0

Возможно, сторонний код также добавляет 'warnings.filterwarnings ('default', category = ResourceWarning)', который будет переопределять ваш, помещаясь перед ним? И если теория @Dunes верна, вы можете перезаписать «warnings.showwarning» в Context Manager с помощью warnings.catch_warnings(): ' – greschd

ответ

15

Я нашел преступника. Вы говорите, что вы устанавливаете свой фильтр во время импорта. Однако, начиная с Python 3.2, модуль unittest был обновлен, чтобы установить фильтр предупреждения по умолчанию. См. Section 29.5.5. В основном, unittest перезаписывает настройки фильтра предупреждений после того, как он завершил импорт ваших модулей.

Например.

my_tests.py

import socket 
import unittest 
import warnings 

warnings.simplefilter("ignore", ResourceWarning) 

def abusesocket(): 
    s = socket.socket() 
    s.connect(("www.google.com", 80)) 

class Test(unittest.TestCase): 

    def test1(self): 
     print("test1") 
     abusesocket() 
     print("module import warning filter nixed") 

    def test2(self): 
     print("test2") 
     warnings.simplefilter("ignore", ResourceWarning) 
     abusesocket() 
     print("higher warning filter okay") 

дает следующий результат

$ python3 -m unittest my_tests.py 
test1 
/home/user/my_tests.py:15: ResourceWarning: unclosed <socket.socket fd=3, family=AddressFamily.AF_INET, type=SocketType.SOCK_STREAM, proto=0, laddr=('x.x.x.x', 52332), raddr=('31.55.166.217', 80)> 
    abusesocket() 
module import warning filter nixed 
.test2 
higher warning filter okay 
. 
---------------------------------------------------------------------- 
Ran 2 tests in 0.347s 

OK 

Solution

unittest появляется, чтобы сбросить предупреждение фильтра после каждого испытания. Таким образом, вы очистите фильтр в начале каждого теста. Наверное, лучше всего использовать декоратор, чтобы обернуть ваши тестовые функции.

def ignore_warnings(test_func): 
    def do_test(self, *args, **kwargs): 
     with warnings.catch_warnings(): 
      warnings.simplefilter("ignore", ResourceWarning) 
      test_func(self, *args, **kwargs) 
    return do_test 

class Test(unittest.TestCase): 

    @ignore_warnings 
    def test1(self): 
     abusesocket() 
+3

Вы также можете поместить его в 'def setUp (self):' чтобы он был последним для всего тестового примера. –

+0

Нам нужно определить функцию 'ignore_warnings()' для отключения предупреждений? –

+0

Нет. Это всего лишь один из способов сделать это. @ThomasAhle сделал хороший момент, просто поместив фильтр в 'setup'. – Dunes

9

unittest.main (предупреждения = «игнорировать»)

+0

Ваше решение очень элегантно, но как заставить его работать с проверкой: 'python setup.py test'? – user3313834

+0

Где этот код находится в нашем модульном тестовом классе? –

Смежные вопросы