Stefan,
f_lineno can be None for some opcodes, but there shouldn't be trace events if it is.
E.g.
>>> def f():
... try:
... 1/0
... finally:
... pass
...
>>> list(f.__code__.co_lines())
[(0, 2, 1), (2, 4, 2), (4, 12, 3), (12, 16, 5), (16, 18, None), (18, 26, 5)]
Note that the bytecode at offset 16 has no line number, but there should be no events for it.
BUT, before you try and fix your tracing emulation, I repeat my plea.
Please stop trying to mimic CPython internals, and ask for the APIs that you need.