-
-
Notifications
You must be signed in to change notification settings - Fork 34.2k
bpo-28053: Complete and fix custom reducers in multiprocessing. #9959
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Changes from all commits
da4f1be
48e14a0
7f537c1
890f9ad
ed8ff52
8b52a54
49a5804
ac779f9
8a18400
7db88ac
f20e142
210b1dc
5a7132f
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -1187,6 +1187,81 @@ For example: | |
| the data in the pipe is likely to become corrupted, because it may become | ||
| impossible to be sure where the message boundaries lie. | ||
|
|
||
| Custom Reduction | ||
| ~~~~~~~~~~~~~~~~ | ||
|
|
||
| .. currentmodule:: multiprocessing | ||
|
|
||
| Several primitives of the :mod:`multiprocessing` module such as | ||
| :class:`multiprocessing.Queue`, :class:`multiprocessing.connection.Listener` or | ||
| :class:`multiprocessing.connection.Server` need to serialize and deserialize Python | ||
| objects to communicate between processes. Sometimes it is useful to control what | ||
| serialization is to be used for the transport of data in order to support communication | ||
| with different versions of Python, use more performant third party tools or custom | ||
| strategies. | ||
|
|
||
| For this purpose a set of hooks is available to provide alternate implementations of | ||
| the reduction mechanism: | ||
|
|
||
| .. currentmodule:: multiprocessing.reduction | ||
|
|
||
| .. class:: AbstractPickler() | ||
| Abstract base class that can be implemented in order to override specidifc | ||
| methods of the reduction machinery used by multiprocessing. | ||
|
|
||
| .. method:: dump(obj) | ||
| Write a pickled representation of obj to the open file. | ||
|
|
||
| Defaults to :meth:`pickle.Pickle.dump` | ||
|
|
||
| .. classmethod:: loads(bytes_object, *, fix_imports=True, encoding="ASCII", errors="strict") | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Are the optional arguments required? Does
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Also, the method / classmethod asymmetry is weird and doesn't help designing an implementation. Do you think that can be fixed (one way or the other)?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Yes, I find this very weird as well. We can make the What do you think?
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Notice that to instantiate the Pickler class we need to provide a dummy file-like object (probably a StringIO instance). I find that suboptimal as well.
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. The other possibility is making |
||
| Read a pickled object hierarchy from a bytes object and return the reconstituted | ||
| object hierarchy specified therein. | ||
|
|
||
| Defaults to :func:`pickle.loads` | ||
|
|
||
| .. class:: AbstractReducer() | ||
|
|
||
| Abstract base class that can be implemented in order to replace the standard | ||
| reduction mechanism used in multiprocessing | ||
|
|
||
| .. method:: get_pickler_class(): | ||
|
|
||
| This method must return an subclass of :class:`pickler.Pickler` to be used by | ||
|
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. This does not make it very clear the relation ship between
Member
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. That should be |
||
| the multiprocessing reducer mechanism. | ||
|
|
||
| .. currentmodule:: multiprocessing | ||
|
|
||
| .. method:: set_reducer(reduction) | ||
|
|
||
| Sets a reduction instance to be used for serialization and deserialization | ||
| by the module primitive internals. **reduction** must be an instance of a | ||
| subclass of :class:`multiprocessing.reduction.AbstractReducer`. | ||
|
|
||
| .. method:: get_reducer() | ||
|
|
||
| Gets the current reduction class in use by the module's primitive internals. | ||
pablogsal marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
|
|
||
| For example, substituting the reducer class to use the :mod:`pickle` protocol | ||
| version 2 to be able to communicate with a Python 2.x programs.:: | ||
|
|
||
| import multiprocessing | ||
| from multiprocessing.reduction import AbstractReducer, AbstractPickler | ||
|
|
||
| class PicklerProtocol2(AbstractPickler): | ||
| @classmethod | ||
| def dumps(cls, obj, protocol=2): | ||
pablogsal marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return super().dumps(obj, protocol=protocol) | ||
|
|
||
| class PickleProtocol2Reducer(AbstractReducer): | ||
| def get_pickler_class(self): | ||
pablogsal marked this conversation as resolved.
Outdated
Show resolved
Hide resolved
|
||
| return PicklerProtocol2 | ||
|
|
||
| multiprocessing.set_reducer(PickleProtocol2Reducer()) | ||
|
|
||
| Notice that using :meth:`multiprocessing.set_reducer` changes the reducer globally. If | ||
| changing this setting globally is undesirable you could call :meth:`context.set_reducer`, | ||
| where *context* is a context object obtained by calling :func:`get_context`. | ||
|
|
||
| Synchronization primitives | ||
| ~~~~~~~~~~~~~~~~~~~~~~~~~~ | ||
|
|
||
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
You'll need some
versionaddeddirective at some point.There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Should we add this? Technically this PR is fixing the previous implementation, although as the old one was broken, one could argue that we are adding the feature.