a few pythonetc posts

    
      
diff --git a/.gitignore b/.gitignore
index 063dd87..3e331c0 100644
--- a/.gitignore
+++ b/.gitignore
@@ -2,3 +2,4 @@
 *-checkpoint.ipynb
 *.bin
 /snippets/reddit.ipynb
+/tmp.py
diff --git a/pythonetc/README.md b/pythonetc/README.md
index 85aba04..4fb0d5b 100644
--- a/pythonetc/README.md
+++ b/pythonetc/README.md
@@ -40,7 +40,5 @@ These are ideas for future posts. Let me know if you want to write a guest post
 + super()
 + gc
 + trace
-+ atexit
-+ Lazy annotations hype
 + del
 + destructor
diff --git a/pythonetc/atexit.md b/pythonetc/atexit.md
new file mode 100644
index 0000000..cad979f
--- /dev/null
+++ b/pythonetc/atexit.md
@@ -0,0 +1,36 @@
+# atexit
+
+The module [atexit](https://docs.python.org/3/library/atexit.html) allows to register hooks that will be executed when the program terminates.
+
+There are only a few cases when it is NOT executed:
+
++ When `os._exit` (don't confuse with `sys.exit`) is called.
++ When the interpreter failed with a fatal error.
++ When the process is hard-killed. For example, someone executed [kill -9](https://askubuntu.com/a/184074) or the system is ran out of memory.
+
+In all other cases, like an unhandled exception or `sys.exit`, the registered hooks will be executed.
+
+A few use cases:
+
++ Finish pending jobs
++ Send pending log messages into the log system
++ Save interactive interpreter history
+
+However, keep in mind that there is no way to handle unhandled exceptions using `atexit` because it is executed after the exception is printed and disacarded.
+
+```python
+import atexit
+
+atexit.register(print, 'FINISHED')
+1/0
+```
+
+Output:
+
+```plain
+Traceback (most recent call last):
+  File "example.py", line 4, in 
+    1/0
+ZeroDivisionError: division by zero
+FINISHED
+```
diff --git a/pythonetc/faulthandler.md b/pythonetc/faulthandler.md
new file mode 100644
index 0000000..e5a4315
--- /dev/null
+++ b/pythonetc/faulthandler.md
@@ -0,0 +1,34 @@
+# faulthandler
+
+The module [faulthandler](https://docs.python.org/3/library/faulthandler.html) allows to register a handler that will dump the current stack trace in a specific file (stderr by default) upon receiving a specific signal.
+
+Dump stack trace every second:
+
+```python
+import faulthandler
+from time import sleep
+
+faulthandler.dump_traceback_later(
+  timeout=2,
+  repeat=True,
+)
+for i in range(5):
+  print(f"iteration {i}")
+  sleep(1)
+```
+
+Output:
+
+```plain
+iteration 0
+iteration 1
+Timeout (0:00:02)!
+Thread 0x00007f8289147740 (most recent call first):
+  File "tmp.py", line 10 in 
+iteration 2
+iteration 3
+Timeout (0:00:02)!
+Thread 0x00007f8289147740 (most recent call first):
+  File "tmp.py", line 10 in 
+iteration 4
+```
diff --git a/pythonetc/faulthandler2.md b/pythonetc/faulthandler2.md
new file mode 100644
index 0000000..640fc6f
--- /dev/null
+++ b/pythonetc/faulthandler2.md
@@ -0,0 +1,31 @@
+# faulthandler part 2
+
+Now, let's see how to dump stack trace when a specific signal received. We will use [SIGUSR1](https://www.gnu.org/software/libc/manual/html_node/Miscellaneous-Signals.html) but you can do the same for any signal.
+
+```python
+import faulthandler
+from signal import SIGUSR1
+from time import sleep
+
+faulthandler.register(SIGUSR1)
+sleep(60)
+```
+
+Now, in a new terminal, find out the [PID](https://en.wikipedia.org/wiki/Process_identifier) of the interpreter. If the file is named `tmp.py`, this is how you can do it (we add `[]` in grep to exclude the grep itself from the output):
+
+```bash
+ps -ax | grep '[t]mp.py'
+```
+
+The first number in the output is the PID. Now, use it to send the signal for PID 12345:
+
+```bash
+kill -SIGUSR1 12345
+```
+
+And back in the terminal with the running script. You will see the stack trace:
+
+```python
+Current thread 0x00007f22edb29740 (most recent call first):
+  File "tmp.py", line 6 in 
+```
diff --git a/pythonetc/future-annotations.md b/pythonetc/future-annotations.md
new file mode 100644
index 0000000..f7009c2
--- /dev/null
+++ b/pythonetc/future-annotations.md
@@ -0,0 +1,38 @@
+# `from __future__ import annotations` (PEP-563)
+
+[PEP-563](https://www.python.org/dev/peps/pep-0563/) (landed in Python 3.7) introduced postponed evaluation of type annotations. That means, all your type annotations aren't executed at runtime but rather considered strings.
+
+The initial idea was to make it the default behavior in Python 3.10 but it was postponed after negative reaction from the community. In short, it would be in some cases impossible to get type information at runtime which is crucial for some tools like [pydantic](https://github.com/samuelcolvin/pydantic) or [typeguard](https://github.com/agronholm/typeguard). For example, see [pydantic#2678](https://github.com/samuelcolvin/pydantic/issues/2678).
+
+Either way, starting from Python 3.7 you can activate this behavior by adding `from __future__ import annotations` at the beginning of a file. It will improve the import time and allow you to use in annotations objects that aren't defined yet.
+
+For example:
+
+```python
+class A:
+  @classmethod
+  def create(cls) -> A:
+    return cls()
+```
+
+This code will fail at import time:
+
+```python
+Traceback (most recent call last):
+  File "tmp.py", line 1, in 
+    class A:
+  File "tmp.py", line 3, in A
+    def create(cls) -> A:
+NameError: name 'A' is not defined
+```
+
+Now add the magic import, and it will work:
+
+```python
+from __future__ import annotations
+
+class A:
+  ...
+```
+
+Another solution is to manually make annotations strings. So, instead of `-> A:` you could write `-> 'A':`.
diff --git a/pythonetc/union.md b/pythonetc/union.md
new file mode 100644
index 0000000..ea3b0c3
--- /dev/null
+++ b/pythonetc/union.md
@@ -0,0 +1,12 @@
+# Union alias (PEP-604)
+
+[PEP-604](https://www.python.org/dev/peps/pep-0604/) (landed in Python 3.10) introduced a new short syntax for `typing.Union` ([as we predicted](https://t.me/pythonetc/569)):
+
+```python
+def greet(name: str) -> str | None:
+  if not name:
+    return None
+  return f"Hello, {name}"
+```
+
+You already can use it in older Python versions by adding described in the previous post `from __future__ import annotations`, [mypy](http://mypy-lang.org/) will understand you.