Calling a function, that yields, twice

Solution 1:

One of my favorite tools to visualize Python with is PythonTutor.

Basically, you can see that on the first run next(pre_worker) returns the _inner function. Since _inner is inside db_connect_n_clean, it can access all of its variables.

Internally, in Python, _inner contains a reference to db_connectors. You can see the reference under __closure__:

>>> gen = db_connect_n_clean()
>>> inner = next(gen)
>>> inner.__closure__
(<cell at 0x000001B73FE6A3E0: list object at 0x000001B73FE87240>,)
>>> inner.__closure__[0].cell_contents
[]

The name of the reference is the same as the variable:

>>> inner.__code__.co_freevars
('db_connectors',)

Every time this specific function, with this specific __closure__ tries to access the db_connectors, it goes to the same list.

>>> inner(1)
Connect :  1
>>> inner(2)
Connect :  2
>>> inner.__closure__[0].cell_contents
[1, 2]

The original generator gen() is still paused at the first yield:

>>> gen.gi_frame.f_lineno
6  # Gen is stopped at line #6
>>> gen.gi_frame.f_locals["db_connectors"]
[1, 2]

When you advance it again using next() it continues on from the yield and closes everything:

>>> next(gen)
Dispose :  1
Dispose :  2
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
StopIteration

If you wish to understand how do generators work in general, there are plenty of answers and articles on the subject. I wrote this one for example.

If I didn't fully explain the situation, feel free to ask for clarification in the comments!