I am trying to create an app which will launch many processes and monitor their outputs. For this purpose I am creating a dictionary of callbacks as so:
{
'alpha': {
'stdout': <function <lambda> at 0x7f0aa5cbaee0>,
'stderr': <function <lambda> at 0x7f0aa5cbaf70>
},
'beta': {
'stdout': <function <lambda> at 0x7f0aa5cc6040>,
'stderr': <function <lambda> at 0x7f0aa5cc60d0>
},
'gamma': {
'stdout': <function <lambda> at 0x7f0aa5cc6160>,
'stderr': <function <lambda> at 0x7f0aa5cc61f0>
}
}
I am using this code to generate these callbacks
def callback_func(arg, job):
print("job: " + job + ", arg: " + arg + ", job address: " + hex(id(job)))
callbacks = {}
important_var = "hello"
for job in ["alpha", "beta", "gamma"]:
callbacks[job] = {}
callbacks[job]["stdout"] = lambda x: callback_func(x, job)
callbacks[job]["stderr"] = lambda x: callback_func(x, job)
print(callbacks)
for jobname in callbacks:
print("Testing callbacks for " + jobname)
callbacks[jobname]["stdout"]("STDOUT test")
callbacks[jobname]["stderr"]("STDERR test")
print("")
However this code results in:
Testing callbacks for alpha
job: gamma, arg: STDOUT test, job address: 0x7f21b5a74c70
job: gamma, arg: STDERR test, job address: 0x7f21b5a74c70
Testing callbacks for beta
job: gamma, arg: STDOUT test, job address: 0x7f21b5a74c70
job: gamma, arg: STDERR test, job address: 0x7f21b5a74c70
Testing callbacks for gamma
job: gamma, arg: STDOUT test, job address: 0x7f21b5a74c70
job: gamma, arg: STDERR test, job address: 0x7f21b5a74c70
Even though the callbacks were generated with different job
arguments they still insist on using the last job
argument.
I ended up using intermediary objects as described here. So my code looks like this:
def callback_func(arg, job):
print("job: " + job + ", arg: " + arg + ", job address: " + hex(id(job)))
class Callback(object):
def __init__(self, job):
self.job = job
def __call__(self, arg):
callback_func(self.job, arg)
callbacks = {}
important_var = "hello"
for job in ["alpha", "beta", "gamma"]:
callbacks[job] = {}
callbacks[job]["stdout"] = Callback(job)
callbacks[job]["stderr"] = Callback(job)
print(callbacks)
for jobname in callbacks:
print("Testing callbacks for " + jobname)
callbacks[jobname]["stdout"]("STDOUT test")
callbacks[jobname]["stderr"]("STDERR test")
print("")
But why was this even necessary? Even if I included job = copy.deepcopy(job)
it still refused to work correctly.