Problem 576871 · easy · Level 05 Advanced Algorithms & Graphs

Keep Going, but Write It Down

py-context-managers · py-classes · py-exceptions · __enter__/__exit__ · error handling

An import script reads thousands of rows. A bad row should not stop the import, but it must not vanish silently either. Write a class Collector(*types) whose objects are context managers used once per row:

errors = Collector(ValueError)
for row in rows:
    with errors:
        import_one(row)
  • with errors: gives the collector itself to as, if one is written.
  • If the block raises an exception that is an instance of one of types (subclasses included), the exception is stopped there and recorded, and the program continues after the block.
  • Any other exception is not recorded and continues to the caller as usual.
  • blocks counts the with blocks entered so far (starting at 0).
  • messages is the list of recorded errors, oldest first, each written as "<block>: <exception type name>: <exception text>", where <block> is the number of the block in which it happened (the first block is 1) and the text is str(exception).

Setup helpers that use a Collector in with blocks, available with Run: import_rows(rows), lookups(keys, table), not_mine() and quiet_run(n).

Examples

Input:  import_rows(["ana, 31", "ben,x", "chen,40", "dev", "eli,200"])
Output: ([("ana", 31), ("chen", 40)],
         ["2: ValueError: invalid literal for int() with base 10: 'x'",
          "4: ValueError: not enough values to unpack (expected 2, got 1)",
          "5: ValueError: age out of range: 200"],
         5)

Constraints

  • At least one exception type is given.
  • Up to 10**4 blocks per collector.

Goals

  • Write a class-based context manager with `__enter__` and `__exit__`
  • Swallow only chosen exception types by returning `True` from `__exit__`
  • Keep state across many uses of the same context manager
Starting Python…