dill.dump_session 无法使用 getpass

dill.dump_session not working with getpass

我有一个 Jupyter 笔记本,我想使用 dill.dump_session 保存其状态,但是如果笔记本使用 getpass 模块,该函数会抛出错误。有什么办法解决这个问题吗? 我理解不转储密码的意义,但我仍然想保存所有其他变量,而无需手动遍历所有变量。

这是我的代码的玩具示例:

import dill
from getpass import getpass

dill.dump_session('../session_dump/sess_test.pkl')

这是我得到的错误:

TypeError                                 Traceback (most recent call last)
<ipython-input-8-5758b730705e> in <module>
----> 1 dill.dump_session('../session_dump/sess_test.pkl')

~\Anaconda3\lib\site-packages\dill\_dill.py in dump_session(filename, main, byref)
    391         pickler._recurse = False # disable pickling recursion for globals
    392         pickler._session = True  # is best indicator of when pickling a session
--> 393         pickler.dump(main)
    394     finally:
    395         if f is not filename:  # If newly opened file

~\Anaconda3\lib\pickle.py in dump(self, obj)
    435         if self.proto >= 4:
    436             self.framer.start_framing()
--> 437         self.save(obj)
    438         self.write(STOP)
    439         self.framer.end_framing()

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_module(pickler, obj)
   1267                 + ["__builtins__", "__loader__"]]
   1268             pickler.save_reduce(_import_module, (obj.__name__,), obj=obj,
-> 1269                                 state=_main_dict)
   1270             log.info("# M1")
   1271         else:

~\Anaconda3\lib\pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    660 
    661         if state is not None:
--> 662             save(state)
    663             write(BUILD)
    664 

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_module_dict(pickler, obj)
    900             # we only care about session the first pass thru
    901             pickler._session = False
--> 902         StockPickler.save_dict(pickler, obj)
    903         log.info("# D2")
    904     return

~\Anaconda3\lib\pickle.py in save_dict(self, obj)
    854 
    855         self.memoize(obj)
--> 856         self._batch_setitems(obj.items())
    857 
    858     dispatch[dict] = save_dict

~\Anaconda3\lib\pickle.py in _batch_setitems(self, items)
    880                 for k, v in tmp:
    881                     save(k)
--> 882                     save(v)
    883                 write(SETITEMS)
    884             elif n:

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_instancemethod0(pickler, obj)
   1076     log.info("Me: %s" % obj) #XXX: obj.__dict__ handled elsewhere?
   1077     if PY3:
-> 1078         pickler.save_reduce(MethodType, (obj.__func__, obj.__self__), obj=obj)
   1079     else:
   1080         pickler.save_reduce(MethodType, (obj.im_func, obj.im_self,

~\Anaconda3\lib\pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    636         else:
    637             save(func)
--> 638             save(args)
    639             write(REDUCE)
    640 

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\pickle.py in save_tuple(self, obj)
    769         if n <= 3 and self.proto >= 2:
    770             for element in obj:
--> 771                 save(element)
    772             # Subtle.  Same as in the big comment below.
    773             if id(obj) in memo:

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    547 
    548         # Save the reduce() output and finally memoize the object
--> 549         self.save_reduce(obj=obj, *rv)
    550 
    551     def persistent_id(self, obj):

~\Anaconda3\lib\pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    660 
    661         if state is not None:
--> 662             save(state)
    663             write(BUILD)
    664 

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_module_dict(pickler, obj)
    900             # we only care about session the first pass thru
    901             pickler._session = False
--> 902         StockPickler.save_dict(pickler, obj)
    903         log.info("# D2")
    904     return

~\Anaconda3\lib\pickle.py in save_dict(self, obj)
    854 
    855         self.memoize(obj)
--> 856         self._batch_setitems(obj.items())
    857 
    858     dispatch[dict] = save_dict

~\Anaconda3\lib\pickle.py in _batch_setitems(self, items)
    880                 for k, v in tmp:
    881                     save(k)
--> 882                     save(v)
    883                 write(SETITEMS)
    884             elif n:

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_module_dict(pickler, obj)
    900             # we only care about session the first pass thru
    901             pickler._session = False
--> 902         StockPickler.save_dict(pickler, obj)
    903         log.info("# D2")
    904     return

~\Anaconda3\lib\pickle.py in save_dict(self, obj)
    854 
    855         self.memoize(obj)
--> 856         self._batch_setitems(obj.items())
    857 
    858     dispatch[dict] = save_dict

~\Anaconda3\lib\pickle.py in _batch_setitems(self, items)
    880                 for k, v in tmp:
    881                     save(k)
--> 882                     save(v)
    883                 write(SETITEMS)
    884             elif n:

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    547 
    548         # Save the reduce() output and finally memoize the object
--> 549         self.save_reduce(obj=obj, *rv)
    550 
    551     def persistent_id(self, obj):

~\Anaconda3\lib\pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    660 
    661         if state is not None:
--> 662             save(state)
    663             write(BUILD)
    664 

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_module_dict(pickler, obj)
    900             # we only care about session the first pass thru
    901             pickler._session = False
--> 902         StockPickler.save_dict(pickler, obj)
    903         log.info("# D2")
    904     return

~\Anaconda3\lib\pickle.py in save_dict(self, obj)
    854 
    855         self.memoize(obj)
--> 856         self._batch_setitems(obj.items())
    857 
    858     dispatch[dict] = save_dict

~\Anaconda3\lib\pickle.py in _batch_setitems(self, items)
    885                 k, v = tmp[0]
    886                 save(k)
--> 887                 save(v)
    888                 write(SETITEM)
    889             # else tmp is empty, and we're done

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    547 
    548         # Save the reduce() output and finally memoize the object
--> 549         self.save_reduce(obj=obj, *rv)
    550 
    551     def persistent_id(self, obj):

~\Anaconda3\lib\pickle.py in save_reduce(self, func, args, state, listitems, dictitems, obj)
    660 
    661         if state is not None:
--> 662             save(state)
    663             write(BUILD)
    664 

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    502         f = self.dispatch.get(t)
    503         if f is not None:
--> 504             f(self, obj) # Call unbound method with explicit self
    505             return
    506 

~\Anaconda3\lib\site-packages\dill\_dill.py in save_module_dict(pickler, obj)
    900             # we only care about session the first pass thru
    901             pickler._session = False
--> 902         StockPickler.save_dict(pickler, obj)
    903         log.info("# D2")
    904     return

~\Anaconda3\lib\pickle.py in save_dict(self, obj)
    854 
    855         self.memoize(obj)
--> 856         self._batch_setitems(obj.items())
    857 
    858     dispatch[dict] = save_dict

~\Anaconda3\lib\pickle.py in _batch_setitems(self, items)
    880                 for k, v in tmp:
    881                     save(k)
--> 882                     save(v)
    883                 write(SETITEMS)
    884             elif n:

~\Anaconda3\lib\pickle.py in save(self, obj, save_persistent_id)
    522             reduce = getattr(obj, "__reduce_ex__", None)
    523             if reduce is not None:
--> 524                 rv = reduce(self.proto)
    525             else:
    526                 reduce = getattr(obj, "__reduce__", None)

~\Anaconda3\lib\site-packages\zmq\backend\cython\socket.cp37-win_amd64.pyd in zmq.backend.cython.socket.Socket.__reduce_cython__()

TypeError: no default __reduce__ due to non-trivial __cinit__

正如所讨论的 here 问题来自 getpass 引用 sys.stdout,它在 jupyter 笔记本中 运行 时引用了 zmq 套接字。事实上,在常规 .py 脚本中尝试没有问题。

在笔记本中使用它的一个简单解决方案是在 dill.dump_session 之前添加 del getpass,例如:

import dill
from getpass import getpass

pwd = getpass("Insert password: ")
del getpass

dill.dump_session('../session_dump/sess_test.pkl')