September 8th, 2015

404

thread_timeout

Эпик фейл. Оно оказалось непригодно IRL из-за нюансиков с эксепшенами.

Если быть точным, то эксепшены не обрабатываются нормально (что очевидно для тредов, да, свой стек, всё такое). Это одно - надо будет дописать, чтобы эксепшены ловились и отдавались обратно в декоратор и рейзились в родительском потоке. (кто тут фанат wrapt'а, как эту проблему решают-то? Чтобы в трейсе было место, где оно первый раз возникло, а не где его повторно рейзнули)

Но интереснее другое.

Вот такой вот невинный код:

def test8():
    '''Check if exceptions are handled properly
    '''
    @thread_timeout(1)
    def exception():
        raise ValueError
    try:
        exception()
    except ValueError:
        print("ok")


Приводит к тому, что после эксепшена программа не завершается а висит бесконечно (хотя и убивается kill'ом).

При этом альтернативная версия отрабатывает с заврешением:
import threading

def inner_worker():
    raise IOError

thread = threading.Thread(target=inner_worker)
thread.daemon = True
thread.start()
thread.join(0.1)
print thread.isAlive()


То есть что-то плохое нахимичено в процессе.

Зато стекирование декораторов работает.

Вот такой тест не проходит, но хотя бы завершается (внимание на декоратор перед тестом):
@thread_timeout(2)
def test8():
    '''Check if exceptions are handled properly
    '''
    @thread_timeout(1)
    def exception():
        raise ValueError
    try:
        exception()
    except ValueError:
        print("ok")


UPD:

Забавно, но после того, как я починил перерейз эксепшенов, проблема прошла. Возможно дело в "инжеткировании" постороннего exception'а. Или ещё чём-то. Мне это не нравится, но как чинить не понимаю.
404

О культурном трейсбэке

Вот так вот выглядит трейс из обычной функции:
Traceback (most recent call last):
  File "1.py", line 11, in 
    foo()
  File "1.py", line 9, in foo
    boo()
  File "1.py", line 6, in boo
    file('/fdf','r')
IOError: [Errno 2] No such file or directory: '/fdf'


А вот так вот - с thread_timeout:
Traceback (most recent call last):
  File "1.py", line 11, in 
    foo()
  File "1.py", line 9, in foo
    boo()
  File "/github/thread_timeout/thread_timeout/__init__.py", line 116, in inner_worker
    result = wrapped(*args, **kwargs)
  File "1.py", line 6, in boo
    file('/fdf','r')



Нормально? Или мне надо напрячься и научиться прятать себя из трейса? То есть как правильнее? Ща на стековерфолу спрошу.

UPD: http://stackoverflow.com/questions/32464682/should-i-hide-decorator-from-the-trace-of-the-decorated-function-python
404

Триггеры народу!ё

Я негодую. Мой второй супергениальный проект с генерацией событий в игре кончился фейлом.

Я решил сделать триггер (штуку, которая один раз сработав, сохраняет это состояние), пока без "rst", который легко приделать на инверторе при необходимости.

Так вот, он не работает! Потому что после замыкания канала сигнал передаётся, но не обрабатывается.

Proof of failure:



Пока что единственным разумным методом автогенерации, который я пока придумал (не завязанным на входные блоки) является циклический конвейер с сенсором и блоком на конвейере.

В принципе, даже циклический не нужен. Вот минимальный генератор с периодом 2 (легко тюнится до любой другой частоты), период 2 - минимально возможный (т.к. период 1 - это "всегда").



Но это не интересно. Во-первых это генератор, а не триггер. В принципе, на базе конвейеров можно собирать элементарную логику, но оно будет большим и некрасивым. Я бы хотел самоподдерживающиеся генераторы и логику в рамках одного события, а не последовательности.

А вот чего бы мне хотелось увидеть - так это изменитель скважности. Чтобы одиночное событие от счётчика давало бы заданную продолжительность активации. Например "пять тиков". Или десять.

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

Мне удалось сделать генератор со стартом (когда генерация начинается после сигнала), но сделать удлиннитель сигнала пока не удаётся. Забавно.