New backend fails if logger set up with additional handlers
See original GitHub issueConsider this code:
import logging
import time
import sys
# from sklearn.externals.joblib import Parallel, delayed
from joblib import Parallel, delayed
logger = logging.getLogger()
formatter = logging.Formatter(
'%(asctime)s %(levelname)s: %(message)s '
'[in %(pathname)s:%(lineno)d]')
handler = logging.StreamHandler(sys.stdout)
handler.setFormatter(formatter)
logger.addHandler(handler)
def func(i):
logger.warning(f"Function calling {i}")
time.sleep(0.5)
with Parallel(n_jobs=4) as parallel:
parallel(delayed(func)(i) for i in range(10))
When running with the sklearn
version of joblib
it produces the following output:
2018-02-20 16:30:50,960 WARNING: Function calling 0 [in log_test.py:18]
2018-02-20 16:30:50,963 WARNING: Function calling 1 [in log_test.py:18]
2018-02-20 16:30:50,963 WARNING: Function calling 2 [in log_test.py:18]
2018-02-20 16:30:50,965 WARNING: Function calling 3 [in log_test.py:18]
2018-02-20 16:30:51,461 WARNING: Function calling 4 [in log_test.py:18]
2018-02-20 16:30:51,464 WARNING: Function calling 5 [in log_test.py:18]
2018-02-20 16:30:51,464 WARNING: Function calling 6 [in log_test.py:18]
2018-02-20 16:30:51,466 WARNING: Function calling 7 [in log_test.py:18]
2018-02-20 16:30:51,962 WARNING: Function calling 8 [in log_test.py:18]
2018-02-20 16:30:51,965 WARNING: Function calling 9 [in log_test.py:18]
If running it on the current git head, it fails:
joblib.externals.loky.process_executor._RemoteTraceback:
"""
Traceback (most recent call last):
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/loky/backend/queues.py", line 150, in _feed
obj, reducers=reducers)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/loky/backend/reduction.py", line 145, in dumps
p.dump(obj)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/parallel.py", line 140, in __getstate__
for func, args, kwargs in self.items]
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/parallel.py", line 140, in <listcomp>
for func, args, kwargs in self.items]
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 881, in dumps
cp.dump(obj)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 268, in dump
return Pickler.dump(self, obj)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 409, in dump
self.save(obj)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 405, in save_function
self.save_function_tuple(obj)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 553, in save_function_tuple
save(state)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 521, in save
self.save_reduce(obj=obj, *rv)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 634, in save_reduce
save(state)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 781, in save_list
self._batch_appends(obj)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 808, in _batch_appends
save(tmp[0])
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 521, in save
self.save_reduce(obj=obj, *rv)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 634, in save_reduce
save(state)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 496, in save
rv = reduce(self.proto)
TypeError: can't pickle _thread.RLock objects
"""
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "log_test.py", line 24, in <module>
parallel(delayed(func)(i) for i in range(10))
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/parallel.py", line 813, in __call__
self.retrieve()
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/parallel.py", line 714, in retrieve
self._output.extend(job.get(timeout=self.timeout))
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/_parallel_backends.py", line 468, in wrap_future_result
return future.result(timeout=timeout)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/loky/_base.py", line 424, in result
return self.__get_result()
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/loky/_base.py", line 382, in __get_result
raise self._exception
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/loky/backend/queues.py", line 150, in _feed
obj, reducers=reducers)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/loky/backend/reduction.py", line 145, in dumps
p.dump(obj)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/parallel.py", line 140, in __getstate__
for func, args, kwargs in self.items]
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/parallel.py", line 140, in <listcomp>
for func, args, kwargs in self.items]
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 881, in dumps
cp.dump(obj)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 268, in dump
return Pickler.dump(self, obj)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 409, in dump
self.save(obj)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 405, in save_function
self.save_function_tuple(obj)
File "/home/javier/anaconda3/lib/python3.6/site-packages/joblib/externals/cloudpickle/cloudpickle.py", line 553, in save_function_tuple
save(state)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 521, in save
self.save_reduce(obj=obj, *rv)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 634, in save_reduce
save(state)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 781, in save_list
self._batch_appends(obj)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 808, in _batch_appends
save(tmp[0])
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 521, in save
self.save_reduce(obj=obj, *rv)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 634, in save_reduce
save(state)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 476, in save
f(self, obj) # Call unbound method with explicit self
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 821, in save_dict
self._batch_setitems(obj.items())
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 847, in _batch_setitems
save(v)
File "/home/javier/anaconda3/lib/python3.6/pickle.py", line 496, in save
rv = reduce(self.proto)
TypeError: can't pickle _thread.RLock objects
The error originates from the assignment of a handler to the logger (code works if the handler is removed, obviously without the fancy formatting). This was the cause of the second error mentioned in https://github.com/joblib/joblib/issues/629#issuecomment-364158151
Issue Analytics
- State:
- Created 6 years ago
- Reactions:1
- Comments:5 (4 by maintainers)
Top Results From Across the Web
Logger v1.11.2 - HexDocs
The event manager and all added event handlers are automatically supervised by Logger . Note that if a backend fails to start by...
Read more >Python Logging: In-Depth Tutorial - Toptal
The Python logging module comes with the standard library and provides basic logging features. By setting it up correctly, a log message can...
Read more >Python Logging Guide - Best Practices and Hands-on Examples
An alert handler that formats ERROR and CRITICAL log requests via the detailed formatter and emails the resulting log entry to the given...
Read more >ValueError: Unable to configure handler 'file': [Errno 2] No ...
What happens is there is some problem with your code happening. Handler catches this error to save it to your log file so...
Read more >Best Practices for Client-Side Logging and Error Handling in ...
The only downside of this method is that you must set up your ... your own logging service, they require a lot of...
Read more >Top Related Medium Post
No results found
Top Related StackOverflow Question
No results found
Troubleshoot Live Code
Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start FreeTop Related Reddit Thread
No results found
Top Related Hackernoon Post
No results found
Top Related Tweet
No results found
Top Related Dev.to Post
No results found
Top Related Hashnode Post
No results found
Top GitHub Comments
As a work-around, your best bet is to define the logger in a helper function:
More details: another work-around is to give a name to the logger. cloudpickle seems to have a bug when pickling the root logger that it does not have when pickling other loggers. In this case though, the formatter is lost with the loky backend, so the get_logger function is probably the best thing to do.
Following from https://github.com/joblib/joblib/issues/634#issuecomment-367321025, I was still unable to get a StreamHandler working when using loky in a Jupyter notebook, but when naming the logger as suggested, as well as setting the level to the logger, the following works for writing a log file.