Is this code thread-safe?
"reasonably safe against deadlocks" is a strange expression :)
In ThreadsnQueues the if func is not None: can be turned into an else.
Your code in ThreadScore indicates that some exceptions might be expected because you handle them and continue. The problem is if that happens while you have the semaphore acquired then it will not release it. You should move the release into finally block.
In choose you join on all threads in multiple places and this code [ p.join(5.0) for p in procs ] gets repeated several times. Should be refactored into a method.
I'm not sure what the point of the semaphore is. The way I read you code is:


You initialize the semaphore with N
Then you spawn N threads each calling acquire/release in it's run method.


This means that all threads can simultaneously enter the block protected by the semaphore. So what's the point of having it?
In ThreadScore.run() the main part is the while True loop. However it never seems to take anything of the queue (it only seems to do it once at the beginning of the run method) so how does it work?