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
BUG: ndarrays pickled by 1.16 cannot be loaded by 1.15.4 and lower #12842
Conversation
Lots of test failures. |
There is a |
3.5 fails because I used fstrings. Since the test is marked slow, and we only run slow on 3.6, I will skip 3.5 altogether. 3.6 is failing tests that check stdout, since the output is getting clobbered with "Coverage.py warning: --include is ignored because --source is set (include-ignored)". Did something change in coverage? Is this just on this PR or elsewhere too? |
Cannot backport if it uses fstrings. |
06adfdd
to
abc604f
Compare
Removed fstrings, rebased off master, but the test still causes problems on travis. It seems creating a venv via I am not sure why the |
numpy/core/tests/test_regression.py
Outdated
@pytest.mark.skipif(not sys.platform.startswith('linux'), | ||
reason="linux only") | ||
@pytest.mark.skipif(sys.version_info < (3,4), reason="lacks venv") | ||
@pytest.mark.skip("venv on travis is flakey") |
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.
Skip the test entirely for now, maybe someday re-enable. It passes when run alone (--k test_pickle_across_versions
) which gives me confidence that the actual fix works
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.
How about just look at the pickle header?
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.
Hmm, OK, looks like pickle itself determines the module, but it must be in the header somewhere. I wonder if the pickle can simply be searched for the module name? For instance
In [30]: a = array(1)
In [31]: pickle.dumps(a, protocol=4)
Out[31]: b'\x80\x04\x95\x96\x00\x00\x00\x00\x00\x00\x00\x8c\x1cnumpy.core._multiarray_umath\x94\x8c\x0c_reconstruct\x94\x93\x94\x8c\x05numpy\x94\x8c\x07ndarray\x94\x93\x94K\x00\x85\x94C\x01b\x94\x87\x94R\x94(K\x01)h\x03\x8c\x05dtype\x94\x93\x94\x8c\x02i8\x94K\x00K\x01\x87\x94R\x94(K\x03\x8c\x01<\x94NNNJ\xff\xff\xff\xffJ\xff\xff\xff\xffK\x00t\x94b\x89C\x08\x01\x00\x00\x00\x00\x00\x00\x00\x94t\x94b.'
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.
Looking at that, I wonder why the umath module is there? Maybe from the ndarray __reduce__
method? AFAICT that method should not be called, being replaced by __reduce_ex__
. I think we should look at both those methods.
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.
We should also test the different protocols.
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.
If you really want to test across versions, could also pickle some ndarray in an earlier version, get the hash of the result, and check that it agrees with the hash of the same data pickled with a latter version. The "correct" hashes can be stored in the test.
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.
For instance with current master and previous array
In [43]: hashlib.sha256(s).hexdigest()
Out[43]: 'cce278984d68606f0ceb4d23c298ebd8abe944adba1bc6b161f16c180e785fc3'
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.
The array_reduce
function does look buggy, but it is unlikely it gets called unless some ndarray subclass does it explicitly.
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.
I wonder why the umath module is there
The module is _multiarray_umath
.
I will write a test that checks the bytestring for the correct module name in all protocols. Tieing ourselves to the exact pickle bytestring or hash seems too restrictive going forward.
There is also some ufunc pickling stuff in |
The ufunc pickles look OK. |
Is |
|
abc604f
to
a21bc6a
Compare
a21bc6a
to
74be893
Compare
74be893
to
4b9d20a
Compare
azure-pipelines.yml
Outdated
@@ -14,7 +14,7 @@ jobs: | |||
docker pull i386/ubuntu:bionic | |||
docker run -v $(pwd):/numpy i386/ubuntu:bionic /bin/bash -c "cd numpy && \ | |||
apt-get -y update && \ | |||
apt-get -y install python3.6-dev python3-pip locales && \ | |||
apt-get -y install python3.6-dev python3-venv python3-pip locales && \ |
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.
No longer need python3-venv
?
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.
True, but on the other hand it couldn't hurt and makes this environment consistent with the other linux ones one travis
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.
Come, come, you could install lots of things that don't hurt, but that is not a reason to do it.
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.
ok, removing
LGTM, one possible nit. |
4b9d20a
to
2b5b009
Compare
Thanks Matti. |
Fixes #12837
When pickling ndarrays, the pickle protocol adds the reconstructing function's module
name to the pickled string so it can be called. The function (which is
_reconstruct) now lives in
numpy.core._multiarray_umath, but in pre-1.16 numpy it was in
numpy.core.multiarray. Also for scalar objects, the function
scalar` moved.The fix is very simple, changing the
__module__
attribute of_reconstruct
andscalar
In
array_reduce_ex
, used when the pickle protocol is 5, the function will benumpy.core.numeric._frombuffer
, which will not exist on pre-1.16 numpy (added in commit 64a855f, Oct 2018). I don't think we can work around that. People who do not have that function will have to modify their numpy if they wish to import protocol-5 pickled ndarrays.