diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 030d44a3f..4dd3da055 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -47,6 +47,7 @@ import imp import io import itertools +import logging import opcode import operator import pickle @@ -569,6 +570,12 @@ def save_inst(self, obj): Supports __transient__""" cls = obj.__class__ + # Try the dispatch table (pickle module doesn't do it) + f = self.dispatch.get(cls) + if f: + f(self, obj) # Call unbound method with explicit self + return + memo = self.memo write = self.write save = self.save @@ -795,6 +802,11 @@ def inject_addons(self): """Plug in system. Register additional pickling functions if modules already loaded""" pass + def save_logger(self, obj): + self.save_reduce(logging.getLogger, (obj.name,), obj=obj) + + dispatch[logging.Logger] = save_logger + # Tornado support diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index 19f1faf1f..6e1a69318 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -1,16 +1,26 @@ from __future__ import division -import imp -import unittest -import pytest -import pickle -import sys -import random + +import base64 import functools +import imp +from io import BytesIO import itertools +import logging +from operator import itemgetter, attrgetter +import pickle import platform -import textwrap -import base64 +import random import subprocess +import sys +import textwrap +import unittest + +try: + from StringIO import StringIO +except ImportError: + from io import StringIO + +import pytest try: # try importing numpy and scipy. These are not hard dependencies and @@ -27,16 +37,6 @@ except ImportError: tornado = None - -from operator import itemgetter, attrgetter - -try: - from StringIO import StringIO -except ImportError: - from io import StringIO - -from io import BytesIO - import cloudpickle from cloudpickle.cloudpickle import _find_module, _make_empty_cell, cell_set @@ -507,6 +507,28 @@ def test_cell_manipulation(self): msg='cell contents not set correctly', ) + def test_logger(self): + logger = logging.getLogger('cloudpickle.dummy_test_logger') + pickled = pickle_depickle(logger) + self.assertTrue(pickled is logger, (pickled, logger)) + + dumped = cloudpickle.dumps(logger) + + code = """if 1: + import cloudpickle, logging + + logging.basicConfig(level=logging.INFO) + logger = cloudpickle.loads(%(dumped)r) + logger.info('hello') + """ % locals() + proc = subprocess.Popen([sys.executable, "-c", code], + stdout=subprocess.PIPE, + stderr=subprocess.STDOUT) + out, _ = proc.communicate() + self.assertEqual(proc.wait(), 0) + self.assertEqual(out.strip().decode(), + 'INFO:cloudpickle.dummy_test_logger:hello') + if __name__ == '__main__': unittest.main()