Skip to main content

how well do you know python, part 5

I was reminded of this one while working on the Spyce/Durus demo to make it a better example of using Durus in a real application.

What is wrong with the following code?

A.py:

import time, threading

finished = False

def foo():
    import sys
    sys.stderr.write('testing')
    global finished
    finished = True

threading.Thread(target=foo).start()
while not finished:
    time.sleep(1)

B.py:

import A

print 'finished'

Update: fixed A.py so there was only one problem.

Comments

Anonymous said…
The most obvious thing wrong is that finished isn't declared global in A.foo() so I think the thread should run and complete but the global finished variable will never be True.

If that's it, you've done a good job of hiding a really obvious problem by introducing threading into the mix. It took me a while to see it because I was expecting something to be wrong with the threading logic.

Which is interesting. I've always sworn threading introduces a whole slew of new problems and should be avoided if at all possible but I never considered that it might also have the effect of hiding well-known problems. :)

Nice.
Jonathan Ellis said…
Actually, that wasn't the problem I intended -- oops! Fixed in the post now. (That's a hint for you -- the problematic behavior that remains gives the same symptom as leaving off the global. :)
Anonymous said…
I/O blocking... one writes to STDERR, the other to STDOUT (via print)? The correct way to do it would be to use a threading.Event object
Anonymous said…
Let me simplify what others are saying: "It uses threads."
Anonymous said…
Hmmm. Well I'm wrong. At least what I thought would work doesn't.

Did I mention how much I dislike threading? ;)
Anonymous said…
I presume the issue is that import sys blocks because of the GIL.

What actually *is* so bad about threading? And what do you use as a cross platform alternative?
Jonathan Ellis said…
Yes, the import blocks. It's actually a separate import lock though, not the GIL. (Unless you redefined GIL to stand for Global Import Lock, but that's not what most people mean. :)
Ian Bicking said…
I'm going to guess that lock has something to do with the threadsafety of imports (which are threadsafe), which means other threads can't access the module until it has finished loading... including perhaps the thread started from the module itself...?
Jonathan Ellis said…
Think of it as an RLock under the import hood: if thread One is doing an import, all other import statements will block until One is done before continuing.

So here, the deadlock is that the main thread has the import lock ("import A"), but since it's waiting for _t to set finished, it will never release the lock and _t is forever stuck at "import sys."
Anonymous said…
The real lesson here is: don't start threads as a side effect of import.
Tim Lesher said…
Nice.
Anonymous said…
I’m currently wrestling with this same issue, and not sure the right way to handle it.

I have a system that automatically starts threads to do background computations. The idea is similar to futures (http://aspn.activestate.com/ASPN/Cookbook/Python/Recipe/84317).

The trouble is that the various functions that are creating these futures might very well be used naïvely in a module of shared utility routines. It’s unreasonable for me to say to the users of the system “Oh, and by the way, you can’t do this.”

Anyway, is there any way to work around this? My own code does not import within functions, but a number of standard library calls *do*. (For example, os.execvp.)

Popular posts from this blog

A week of Windows Subsystem for Linux

I first experimented with WSL2 as a daily development environment two years ago. Things were still pretty rough around the edges, especially with JetBrains' IDEs, and I ended up buying a dedicated Linux workstation so I wouldn't have to deal with the pain.  Unfortunately, the Linux box developed a heat management problem, and simultaneously I found myself needing a beefier GPU than it had for working on multi-vector encoding , so I decided to give WSL2 another try. Here's some of the highlights and lowlights. TLDR, it's working well enough that I'm probably going to continue using it as my primary development machine going forward. The Good NVIDIA CUDA drivers just work. I was blown away that I ran conda install cuda -c nvidia and it worked the first try. No farting around with Linux kernel header versions or arcane errors from nvidia-smi. It just worked, including with PyTorch. JetBrains products work a lot better now in remote development mod...

Python at Mozy.com

At my day job, I write code for a company called Berkeley Data Systems. (They found me through this blog, actually. It's been a good place to work.) Our first product is free online backup at mozy.com . Our second beta release was yesterday; the obvious problems have been fixed, so I feel reasonably good about blogging about it. Our back end, which is the most algorithmically complex part -- as opposed to fighting-Microsoft-APIs complex, as we have to in our desktop client -- is 90% in python with one C extension for speed. We (well, they, since I wasn't at the company at that point) initially chose Python for speed of development, and it's definitely fulfilled that expectation. (It's also lived up to its reputation for readability, in that the Python code has had 3 different developers -- in serial -- with very quick ramp-ups in each case. Python's succinctness and and one-obvious-way-to-do-it philosophy played a big part in this.) If you try it out, pleas...

Why PHP sucks

(July 8 2005) Apparently I got linked by some PHP sites, and while there were a few well-reasoned comments here I mostly just got people who only knew PHP reacting like I told them their firstborn was ugly. These people tended to give variants on one or more themes: All environments have warts, so PHP is no worse than anything else in this respect I can work around PHP's problems, ergo they are not really problems You aren't experienced enough in PHP to judge it yet As to the first, it is true that PHP is not alone in having warts. However, the lack of qualitative difference does not mean that the quantitative difference is insignificant. Similarly, problems can be worked around, but languages/environments designed by people with more foresight and, to put it bluntly, clue, simply don't make the kind of really boneheaded architecture mistakes that you can't help but run into on a daily baisis in PHP. Finally, as I noted in my original introduction, with PHP, ...