LINUX.ORG.RU
ФорумTalks

Прекрасная система тестирования в Python

 , ,


0

2
class Foo():
    def __init__(self):
        print('конструктор')

    def __del__(self):
        print('деструктор')
        raise ValueError('плохой деструктор')


def test_foo():
    f = Foo()
    assert f, 'Инстанцирован'

И собственно работа:

$ pytest -sv test_e.py
=========================== test session starts ============================
platform linux -- Python 3.6.7, pytest-3.7.2, py-1.7.0, pluggy-0.8.1 -- /usr/bin/python3
cachedir: .pytest_cache
rootdir: /home/unera, inifile:
plugins: teamcity-messages-1.21, aiohttp-0.3.0
collected 1 item                                                           

test_e.py::test_foo конструктор
деструктор
Exception ignored in: <bound method Foo.__del__ of <test_e.Foo object at 0x7f5d99c2c198>>
Traceback (most recent call last):
  File "/home/unera/test_e.py", line 7, in __del__
    raise ValueError('плохой деструктор')
ValueError: плохой деструктор
PASSED

========================= 1 passed in 0.03 seconds =========================

Прямо даже уже и не знаю чо сказать. И правда, подумаешь - ну исключение какое-то. Не считать же тестирование неуспешным при этом, правда?

passed, Карл, passed!

★★
Ответ на: комментарий от i-rinat

Там нет и не может быть деструкторов

Да, но в доках ко второму питону написано: деструктор. Вот прямо так без оговорок.

bread
()
Ответ на: комментарий от i-rinat

__del__ можно называть деструктором, но только если в понятие «деструктор» ты вкладываешь ровно то, что написано в доках

Т.е. в питоне как обычно своя уличная терминология.

bread
()
Ответ на: комментарий от bread

Всю доку к __del__ тебе перевести? Губу раскатал.

Ну вот и проблема твоя — ты просто не знаешь английский на достаточном уровне, чтобы прочитать пару абзацев. Вместо этого выдёргиваешь отдельные слова и придумываешь, что бы остальные могли значить.

i-rinat ★★★★★
()

Не понимаю, что удивляет: ты же не тестировал, работает ли «del f». Я бы на месте py.test тоже сказал, что всё ок

michwill ★★★★★
()
Ответ на: комментарий от rsync

В чём проблема вызвать функцию? Я со многим тобой сказанным отчасти могу согласиться, но сейчас ты просто докапываешься до фигни.

Во втором питоне мб где-то в кишках исключения мб можно добыть, хз, мне никогда не нужно было, и влом искать (я с планшетика), но в 3.7 (не знаю когда именно появилось) оно прямо наверху, даже ковыряться не надо:

>>> try:
...   raise Exception("test")
... except Exception as e:
...   print(dir(e.__traceback__))
...
['tb_frame', 'tb_lasti', 'tb_lineno', 'tb_next']
WitcherGeralt ★★
()
Ответ на: комментарий от rsync

И ты можешь его отловить, если напишешь соответствующий тест. Но ты не пишешь, ССЗБ.

WitcherGeralt ★★
()
Ответ на: комментарий от SkyMaverick

Оно не разрушает объект, что должен делать классический деструктор

в большинстве языков, где управление памятью возложено на сам язык, деструктор не разрушает объект, но может выполнять произвольные деинициализации связанные с разрушением объекта

rsync ★★
() автор топика
Ответ на: комментарий от rsync

Конкретно в языках, где есть garbage collector, ты НЕ можешь точно знать МОМЕНТ когда именно GC появится и начнёт деинициализировать и разрушать объекты и появится ли он вообще.

Именно поэтому там и используются финализаторы, а не деструкторы в стиле С++.

SkyMaverick ★★★★★
()
Ответ на: комментарий от crutch_master

Это же тебе не плюсы

будто в плюсах по-другому

В языках с GC всем похер что там происходит с не нужными объектам

в финализаторе может происходить закрытие транзакции например, или файла, вообще освобождение ресурса, если он выкидывает исключение - это плохо

так что, нормальные модульные тесты должны падать, чтобы сразу было видно идиота, который в деструкторе вызывает код, который может выбросить исключение

next_time ★★★★★
()
Ответ на: комментарий от next_time

Полагаться на финализаторы для освобождения важных ресурсов — вот отдельный маразм. По определению сборки мусора у тебя нет никаких способов уверенно контролировать конкретный момент сборки мусора. Весь смысл сборки мусора — перестать заботиться о времени сбора тех или иных объектов.

Если нужно следить за временем жизни ресурса, есть менеджеры контекстов. Для дополнительного удобства можно скрестить с генераторами.

i-rinat ★★★★★
()
Ответ на: комментарий от i-rinat

Полагаться на финализаторы для освобождения важных ресурсов — вот отдельный маразм.

не, это норма - rust и С++ подтверждают

Весь смысл сборки мусора — перестать заботиться о времени сбора тех или иных объектов.

вот я и говорю, нахрен вообще нужен финализатор, зависящий от сборки мусора? память мусоросборщик итак очистит

next_time ★★★★★
()
Ответ на: комментарий от i-rinat

Если нужно следить за временем жизни ресурса, есть менеджеры контекстов

Бывают объекты с неопределённым жизненным циклом, которые нельзя финализировать контекстным менеджером. Хотя сам я фанат и контекстных менеджеров, и генераторов, пихаю их вообще везде, где это к месту, чтобы убрать с глаз долой сопутствующие основной логике операции. Но иногда __del__ очень даже нужен, не зря же он существует и до сих пор не выпилен.

WitcherGeralt ★★
()
Ответ на: комментарий от next_time

нахрен вообще нужен финализатор, зависящий от сборки мусора?

Прекрасная система тестирования в Python (комментарий)

Как минимум в качестве гарантии, что ресурсы освобождены, на случай, если это по какой-то причине не было сделано явно.

WitcherGeralt ★★
()
Ответ на: комментарий от next_time

не, это норма - rust и С++ подтверждают

Ты в курсе, что это не языки со сборкой мусора?

вот я и говорю, нахрен вообще нужен финализатор, зависящий от сборки мусора?

Чтобы ловить таких как ТС на неспособности читать доки.

i-rinat ★★★★★
()
Ответ на: комментарий от WitcherGeralt

Бывают объекты с неопределённым жизненным циклом, которые нельзя финализировать контекстным менеджером.

Счётчик ссылок можно вкорячить же.

не зря же он существует и до сих пор не выпилен

Мне кажется, что если в __del__ какой-то нетривиальный код, то проектирование где-то свернуло не туда.

i-rinat ★★★★★
()
Ответ на: комментарий от next_time

в финализаторе может происходить закрытие транзакции например

Её проще явно закрыть, кмк, чем на что-то там полагаться, а финализатор только в качестве запасного варианта, если скрипт свалился.

crutch_master ★★★★★
()
Ответ на: комментарий от olegd

Перевести?

в Py3.5 он всё еще называется деструктор.

https://docs.python.org/3.5/reference/datamodel.html#object.__del__

Called when the instance is about to be destroyed. This is also called a destructor.

3.6 релизнули 23 декабря 2016, два года назад.

то есть ~20 лет считали деструкторами, два года назад уточнили «лучше называть финалайзерами»

и адептов штырит теперь от слова «деструктор» ППЦ

rsync ★★
() автор топика
Ответ на: комментарий от i-rinat

кажется, что если в __del__ какой-то нетривиальный код, то проектирование где-то свернуло не туда.

почему на С++ можно всунуть в деструктор нетривиальный код (например закрытие файла, сокета, итп), а тут нельзя?

rsync ★★
() автор топика
Последнее исправление: rsync (всего исправлений: 1)
Ответ на: комментарий от i-rinat

Ты в курсе, что это не языки со сборкой мусора?

int foo() {
  int bar;
  int baz;

  // что-то делаем с bar/baz: заполняем какими-то действиями
  return bar + baz;
}

int main() {
  foo();
  // херак: тут всё почищено от выделений bar и baz
}

а вообще деструкторы они ведь не только про память. но и про деинициализацию/завершение действий.

приконнектились к БД. Логично будет что деструктор коннектора сделает дисконнект.

открыли файл. Логично будет что деструктор дескриптора его закроет.

что не так-то?

rsync ★★
() автор топика
Ответ на: комментарий от rsync

почему на С++ можно всунуть в деструктор нетривиальный код (например закрытие файла, сокета, итп), а тут нельзя?

Потому что на C++ деструктор выполняется «внутри» программы. Ты точно можешь указать место в коде, где компилятор вставляет вызов деструктора. В языках со сборкой мусора финализатор вызывается «вне» программы. Ты не знаешь, когда это произойдёт, и не можешь на это повлиять. Всё, что ты можешь — подсказать сборщику мусора, что пора бы. А он имеет полное моральное право твои подсказки игнорировать.

По факту ты можешь вставлять управление ресурсами в __del__, но это просто плохая идея (как и в Perl, лол). В Python для такого есть контексты. Но читать про них тебе придётся самому, когда таки решишь читать документацию. Тут в теме тебе уже десяток раз рассказали — не помогает.

i-rinat ★★★★★
()
Ответ на: комментарий от rsync

приконнектились к БД. Логично будет что деструктор коннектора сделает дисконнект.

Ну так и делают. Только вот ты же подразумеваешь, что только финализатор будет «делать дисконнект». А это не логично. Логично добавить специальный метод, который закроет соединение с базой. Ну и в __del__ добавить его вызов: на случай, если программисту плевать, когда закрывать соединение с базой. В C++ такой метод будет лишним, потому что деструктор вызывается сразу при уходе из области видимости.

открыли файл. Логично будет что деструктор дескриптора его закроет.

Проще контекст заюзать. Там будет видно, когда файл закроется. Ты же не хочешь, чтобы файл таскался открытым неизвестно сколько?

i-rinat ★★★★★
()
Ответ на: комментарий от Deleted

Я в прошлом треде это уже писал. Он по моему специально игнорирует посты где его тыкают носом в его ошибку, а вместо этого разжигает флейм в своих тредах знатно. То есть цель его не научиться а потроллить.

Так что лорчую и тут: язабан.

eternal_sorrow ★★★★★
()
Ответ на: комментарий от rsync

херак: тут всё почищено от выделений bar и baz

ты вообще слышал, что такое стек выполнения и стековые переменные? причём тут GC вообще?

вот если бы внутри foo() была выделена память на куче и не очищена после работы, то эта память останется занятой до конца выполнения программы, никакой GC её не овободит.

в C++ есть условный GC на подсчёте ссылок через std::shared_ptr, std:unique_ptr и.т.д, но это не оно.

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 2)
Ответ на: комментарий от eternal_sorrow

в C++ есть условный GC на подсчёте ссылок через std::shared_ptr, std:unique_ptr и.т.д, но это не оно.

вполне себе оно. и стек - тоже оно.

вся разница только в том что способов побольше, но вариация GС (очистки мусора) есть во всех языках

вот GC как процесс (пусть даже псевдо) - зло в чистом виде. то есть GC, который может в любое время решить что нужно приступить к чистке.

rsync ★★
() автор топика
Ответ на: комментарий от i-rinat

Проще контекст заюзать

да да. из контекста коннектиться к БД. Ага, мы поняли.

rsync ★★
() автор топика
Ответ на: комментарий от i-rinat

Потому что на C++ деструктор выполняется «внутри» программы

потому что выполнять код который пишет пользователь вне программы - неправильно

rsync ★★
() автор топика
Последнее исправление: rsync (всего исправлений: 1)
Ответ на: комментарий от crutch_master

если скрипт свалился, то и сложный финализатор с высокой вероятностью свалится, уж лучше на внешние к скрипту ср-ва полагаться в таком случае

next_time ★★★★★
()
Ответ на: комментарий от i-rinat

Чтобы ловить таких как ТС на неспособности читать доки.

тогда ТС прав: питон - говно, т.к. ЯП проектируют чтобы на них ПО писать, а не чтобы кого-то ловить

next_time ★★★★★
()
Ответ на: комментарий от i-rinat

Чтобы ловить таких как ТС на неспособности читать доки.

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

bread
()
Ответ на: комментарий от rsync

и адептов штырит теперь от слова «деструктор»

Если создать тему «В питоне нет деструкторов», те же адепты налетят и будут доказывать что есть. Как это в питоне чего-то нет, не может быть такого.

bread
()
Ответ на: комментарий от bread

Как это в питоне чего-то нет, не может быть такого

Ну вообще это удивительно, должно быть и обязательно через жопу python way.

no-such-file ★★★★★
()
Ответ на: комментарий от rsync

вполне себе оно

но в твоём примере кода std::shared_ptr и.т.д не использовались. я про него говорил, если ты не понял. просто не стал цитировать весь фрагмент

eternal_sorrow ★★★★★
()
Последнее исправление: eternal_sorrow (всего исправлений: 1)
Ответ на: комментарий от bread

Вы дружно палитесь на слове финализатор, просто ржач.

Для вас стараемся. Вы от слова «деструктор» почему-то лопаетесь и булькаете. Как я уже говорил, можете называть __del__ деструктором, пока вкладываете в него ровно тот смысл, что описан в доках.

Но вы не можете. И поэтому для вас мы используем другое слово — «финализатор». Если у вас слово вызывает приступы булькания… Что ж, ничего не поделаешь.

i-rinat ★★★★★
()
Ответ на: комментарий от rsync

Жили изолированно, затем синхронизировали свою терминологию с общемировой. Чтобы иммигранты с других языков не пытались работать с финализаторами как привыкли с деструкторами. Всё правильно сделали.

olegd ★★★
()
Ответ на: комментарий от olegd

Похоже его руководство совершает серьезную ошибку пересаживаясь с позавчерашней технологии на вчерашнюю. Разумнее либо держаться за легаси, либо быть всегда на острие хайпа. Тем более размен перл — питон это же эталонное шило на мыло.

bread
()
Ответ на: комментарий от bread

Перл труднее читать.
А на чём сейчас принято г..окодить?

Shadow ★★★★★
()
Ответ на: комментарий от Shadow

Нет, одного достаточно, независимо от количества звёзд до этого.

grem ★★★★★
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.