From 77b7ddc5455c8c10043dcbc61f5f6b6f34b4371e Mon Sep 17 00:00:00 2001 From: hyukjinkwon Date: Thu, 3 Aug 2017 11:49:26 +0900 Subject: [PATCH 1/2] Catchs the exception from pickle.whichmodule() --- cloudpickle/cloudpickle.py | 14 ++++++++++++-- 1 file changed, 12 insertions(+), 2 deletions(-) diff --git a/cloudpickle/cloudpickle.py b/cloudpickle/cloudpickle.py index 24fe65fe6..17a1f9529 100644 --- a/cloudpickle/cloudpickle.py +++ b/cloudpickle/cloudpickle.py @@ -310,7 +310,12 @@ def save_function(self, obj, name=None): if name is None: name = obj.__name__ - modname = pickle.whichmodule(obj, name) + try: + # whichmodule() could fail, see + # https://bitbucket.org/gutworth/six/issues/63/importing-six-breaks-pickling + modname = pickle.whichmodule(obj, name) + except Exception: + modname = None # print('which gives %s %s %s' % (modname, obj, name)) try: themodule = sys.modules[modname] @@ -594,7 +599,12 @@ def save_global(self, obj, name=None, pack=struct.pack): modname = getattr(obj, "__module__", None) if modname is None: - modname = pickle.whichmodule(obj, name) + try: + # whichmodule() could fail, see + # https://bitbucket.org/gutworth/six/issues/63/importing-six-breaks-pickling + modname = pickle.whichmodule(obj, name) + except Exception: + modname = '__main__' if modname == '__main__': themodule = None From 4062d3a7c9fdeaccf3f0f8056b6503b7e6c4a608 Mon Sep 17 00:00:00 2001 From: hyukjinkwon Date: Sat, 5 Aug 2017 21:14:50 +0900 Subject: [PATCH 2/2] Add test cases to make sure --- tests/cloudpickle_test.py | 28 ++++++++++++++++++++++++++++ 1 file changed, 28 insertions(+) diff --git a/tests/cloudpickle_test.py b/tests/cloudpickle_test.py index 22f656a77..aa33ce4bf 100644 --- a/tests/cloudpickle_test.py +++ b/tests/cloudpickle_test.py @@ -652,6 +652,34 @@ def __init__(self, x): self.assertEqual(set(weakset), set([depickled1, depickled2])) + def test_ignoring_whichmodule_exception(self): + class FakeModule(object): + def __getattr__(self, name): + # This throws an exception while looking up within + # pickle.whichimodule. + raise Exception() + + class Foo(object): + __module__ = None + + def foo(self): + return "it works!" + + def foo(): + return "it works!" + + foo.__module__ = None + + sys.modules["_fake_module"] = FakeModule() + try: + # Test whichmodule in save_global. + self.assertEqual(pickle_depickle(Foo()).foo(), "it works!") + + # Test whichmodule in save_function. + self.assertEqual(pickle_depickle(foo)(), "it works!") + finally: + sys.modules.pop("_fake_module", None) + if __name__ == '__main__': unittest.main()