Embedded Python : Why does thread lock here?

R

roschler

I have the Python Intepreter embedded in a Delphi (Object Pascal)
program. In the Python script shown below, I have a module that
creates a thread object and starts it. The thread's run() call calls
a function called deleteOutputVariables() declared at the module
level. In my code's first incarnation the thread's run() call would
deadlock when trying to call the deleteOutputVariables() function
declared at Module level. I would never see the statement
"(deleteOutputVariables) Top of Call" printed to the screen. I now
know that I must periodically call join() with a very fast time-out to
keep Python threads happy, and that solved the problem. However I am
curious as to why it deadlocked at the deleteOutputVariables() call?
Is it because deleteOutputVariables() is declared at the module level
or because that function deletes module level variables? If so why?

The code with the relevant parts excerpted is shown below, hopefully
the indents hold up.

Thanks,
Robert

----------------------------

# MODULE: PythonThreadTest.py

# FUNCTION: Delete the variables given in the list.
def deleteOutputVariables(theModule, theOutputVariablesListOfNames):
try:
print "(deleteOutputVariables) Top of call."
for theOutputVariableName in theOutputVariablesListOfNames:
if theModule.__dict__.has_key(theOutputVariableName):
print "(Python::deleteOutputVariables) Deleting the
Output Variable named " + theOutputVariableName
del theModule.__dict__[theOutputVariableName]
except:
print "(deleteOutputVariables) Exception occurred."

# Import needed system modules
import sys, os
from threading import Thread

# ----------------- BEGIN: THREAD class to execute robodanceCommand()
class threadRun(Thread):
def __init__ (self, theJobID = None):
Thread.__init__(self)
self.jobCompleted = False
# def: __init__
def run(self):
try:
# NOTE ---> This is where the thread locks if I don't call
join(0.001) in
# my DELPHI (not Python) loop that waits on the thread to
complete. Once
# theNewThread.join() is called, execution resumes in
# deleteOutputVariables() and the thread completes.
deleteOutputVariables(Test_PYTHON, ["PyOut1"])

# Let others know we are done.
self.jobCompleted = True
except Exception, exc:
self.exceptionCaught = exc
# Let others know we are done.
self.jobCompleted = True
print("(Python::threadRun) Exception occurred.")
# end: try
# def: run()
# ----------------- END: THREAD to execute robodanceCommand()

theNewThread = None
theNewThread = threadRun("TestThread")
theNewThread.start()
 
G

Gabriel Genellina

I have the Python Intepreter embedded in a Delphi (Object Pascal)
program. In the Python script shown below, I have a module that
creates a thread object and starts it.

Do you *execute* the module or do you *import* it?
Isn't a good idea to spawn a thread by side effect of importing a module.
The thread's run() call calls
a function called deleteOutputVariables() declared at the module
level. In my code's first incarnation the thread's run() call would
deadlock when trying to call the deleteOutputVariables() function
declared at Module level. I would never see the statement
"(deleteOutputVariables) Top of Call" printed to the screen. I now
know that I must periodically call join() with a very fast time-out to
keep Python threads happy, and that solved the problem.

What does the Delphi code? Isn't a join with a long timeout enough?
However I am
curious as to why it deadlocked at the deleteOutputVariables() call?
Is it because deleteOutputVariables() is declared at the module level
or because that function deletes module level variables? If so why?

I don't know, but you can make some experiments - move te
deleteOutputVariables as a method, or don't delete module level variables
at all, and see what happens. I'd say both factors are irrelevant.
# FUNCTION: Delete the variables given in the list.
def deleteOutputVariables(theModule, theOutputVariablesListOfNames):
try:
print "(deleteOutputVariables) Top of call."
for theOutputVariableName in theOutputVariablesListOfNames:
if theModule.__dict__.has_key(theOutputVariableName):
print "(Python::deleteOutputVariables) Deleting the
Output Variable named " + theOutputVariableName
del theModule.__dict__[theOutputVariableName]
except:
print "(deleteOutputVariables) Exception occurred."

As a rule, avoid using __special__ names. There is almost never need of
using them (__init__ is a notable exception) unless you want to change
Python behaviour.
In this case:

for theOutputVariableName in theOutputVariablesListOfNames:
if hasattr(theModule, theOutputVariableName):
delattr(theModule, theOutputVariableName)

(a name like theOutputVariablesListOfNames is too long for my taste, but
that's a matter of style...)
theNewThread = None
theNewThread = threadRun("TestThread")

That first line is useless...
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top