Logging and Threads

I have the following code:

@concurrent
def request(flow):
   displayFunction()
   ...

def displayFunction():
    print("[FUNC] {}".format(sys._getframe(1).f_code.co_name))
    ctx.log.info("Test")

The first line of displayFunction works ok, but the next line “ctx.log.info()” fails with this error:

[FUNC] request
Exception in thread ScriptThread:
Traceback (most recent call last):
  File "c:\program files (x86)\python36-32\lib\threading.py", line 916, in _bootstrap_inner
    self.run()
  File "c:\program files (x86)\python36-32\lib\threading.py", line 864, in run
    self._target(*self._args, **self._kwargs)
  File "c:\program files (x86)\python36-32\lib\site-packages\mitmproxy\script\concurrent.py", line 22, in run
    fn(obj)
  File "C:\mitmproxy\pyProxy3.py", line 71, in request
    displayFunction()
  File "C:\mitmproxy\pyProxy3.py", line 1506, in displayFunction()
    ctx.log.info("Test")
AttributeError: 'NoneType' object has no attribute 'info'

What is wrong? Are @concurrent and ctx.log incompatible?

Thanks!

@concurrent spawns a new thread, and ctx may be unavailable outside of the main thread. There are some protections for logging specifically, but in general it’s unsafe to interact with ctx. If you only need logging, log = ctx.log directly after import and then using that from a different thread should work.

If not absolutely required, @concurrent will make things more difficult and slower.

It will make things more difficult in general or for log?

In general - each invocation of a @concurrent function basically spawns a new thread. If you have nothing that blocks in your code, it’s a lot of unnecessary overhead and potential for race conditions.