5
5
.layout = "article.shtml",
6
6
.tags = ["article", "python", "software", "design"],
7
7
.draft = false,
8
- ---
8
+ ---
9
+
10
+ []($section.id("intro"))
11
+ The following shennanigans were collected during my work on creating a system
12
+ integration library and framework for hardware and software tests including
13
+ developer tasks like worktree management, building, target deployment and
14
+ configuration. Therefore it should be representative for things one
15
+ might want to do in absence of better tooling. The used Python version was
16
+ 3.8.2, but most problems still persist.
17
+
18
+ []($section.id("tldr"))
19
+ My [**tldr;**](#tldr) retrospection upfront, which you may be able to reproduce
20
+ once you try to code long-running services, which recover from all failures,
21
+ cleanly reset state or generally try to debug spurious problems. Please don't.
22
+
23
+ Python on itself is great for prototyping up to a few hundred lines of code,
24
+ like to quickly receive or send some json over tcp/html.
25
+ **However**, it is unfeasible to scale, for example to use as library code.
26
+ Changes in a leaf function can add exceptions to higher level code paths and
27
+ handling those via exceptions for user friendly error messages, for example
28
+ to collect context (information along multiple functions, for example from
29
+ different combination of traversal) becomes unreasonably verbose and error
30
+ prone. The alternative is to use C-like error handling, which requires to figure out
31
+ all possible exceptions of Python libstd methods, which language servers
32
+ do not support (as of 20240404).
33
+
34
+ []($section.id("list_of_shame"))
35
+ Aside of these more fundamental limitations, here the [list of shennanigans](#list_of_shennanigans) I have run into:
36
+ - `xml.dom.minidom` [breaks space and newlines](https://bugs.python.org/issue5752). Use `ElementTree`.
37
+ - `.strip()` is necessary after file read, because Python automatically adds
38
+ `\n` and there is no way to read without newlines into a list.
39
+ - Testing for subdictionaries with `dict` is unreadable, so such a method is missing
40
+ [missing_dict_methods1.py]($code.asset('./missing_dict_methods1.py').language('python'))
41
+ - `dict` has no method to check, if the fields of a dictionary are in another dictionary
42
+ [missing_dict_methods2.py]($code.asset('./missing_dict_methods2.py').language('python'))
43
+ - `dict` has no method to check, if all fields and values of a dictionary are in another dictionary
44
+ [missing_dict_methods3.py]($code.asset('./missing_dict_methods3.py').language('python'))
45
+ - Tuples and dicts are annoying to differentiate
46
+ [tup_and_dicts.py]($code.asset('./tup_and_dicts.py').language('python'))
47
+ - Stack trace formatting is inefficient and one can not use <code>gf</code> or <code>gF</code> vim shortcuts to jump to location
48
+ function to write status + trace to variable.
49
+ [stacktrace_fmt.py]($code.asset('./stacktrace_fmt.py').language('python'))
50
+ - Mixed double quote (`"`) and single quote (`'`) strings are invalid json
51
+ [invalid_json.py]($code.asset('./invalid_json.py').language('python'))
52
+ - `os.kill()` does not call registered cleanup function
53
+ `atexit.register(exit_cleanup)` by deamonized threads. Must store pids of
54
+ child processes and clean them explicitly or signal main thread via
55
+ [signal_main_thread.py]($code.asset('./signal_main_thread.py').language('python'))
56
+ - [Socket timeout can cause file-like readline() method to lose data](https://github.com/python/cpython/issues/51571), workaround
57
+ 1. Read from Kernel structure and append chunk-wise to buffer from socket until stop event (via select).
58
+ 2. After each read, try to line a line from the buffer and remove the line on success (being utf-8 etc).
59
+ 3. On failure of reading line, continue with 1.
60
+ 4. Teardown should read socket until being empty, if a stop was obtained.
61
+ - Generic module annotation is not allowed and mypy has no explicit docs for
62
+ this. The following does not work and `module: object` is the closest we can
63
+ get as simple annotation.
64
+ [module_annotation.py]($code.asset('./module_annotation.py').language('python'))
65
+ - There are no scheduling and watchdog methods, which makes Python thread
66
+ scheduling very unreliable. Unlucky schedules may cause fatal delay for
67
+ shuffling data between daemon thread and main thread. As example, an
68
+ application using 1 main thread and 2 deamon threads may cause the relevant
69
+ deamon thread not being scheduled for 2 seconds.
70
+ Empirically 3 seconds work.
71
+ - Trailing comma in dictionary or `json.dumps` generated string has
72
+ silent failures, for example on parsing the output as json via php.
0 commit comments