-
-
Notifications
You must be signed in to change notification settings - Fork 10.9k
BUG: TypeError: add_docstring() argument 2 must be str, not None #13248
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
Comments
Encountered the same issue with cx_freeze. Setting 'build_exe' option 'optimize' to 0 or 1 is a viable workaround. Also adding:
to the beginning of Neither are ideal, but they work if/until this is addressed |
I have to say I'm rather puzzled here. We do have integration tests that verify NumPy works when run with numpy/numpy/core/src/multiarray/compiled_base.c Lines 1412 to 1415 in ca8a22c
Is it possible that these tools don't set Can you verify that you can successfully run your example with NumPy 1.15? |
Also here, will try to build and run the tests. |
Does not reproduce with cpython3.7, pyinstaller3.4, numpy1.16.2 on ubuntu 18.04. Also tried with cpython3.6 and the example works fine. |
Because we do want to copy docstrings from dispatchers when using |
After some deeper checking, building and comparing with NumPy 1.15 build it seems that PyInstaller passes the BUT the output bundle do not store the flag state when it was generated. numpy/numpy/core/src/multiarray/compiled_base.c Lines 1412 to 1415 in ca8a22c
As i see it (i may be wrong) i'm not sure how to continue from here, is this something that needed to be handled in NumPy or PyInstaller? For my scenario this next code did the job without doing changes to NumPy core files: # added in the main module before import numpy
import sys
if __doc__ is None and hasattr(sys, 'frozen'):
from ctypes import c_int, pythonapi
c_int.in_dll(pythonapi, 'Py_OptimizeFlag').value = 2 or more generic: def frozen_oo():
"""Check if code is frozen with optimization=2"""
import sys
if frozen_oo.__doc__ is None and hasattr(sys, 'frozen'):
from ctypes import c_int, pythonapi
c_int.in_dll(pythonapi, 'Py_OptimizeFlag').value = 2
frozen_oo()
import numpy as np
... |
I think this is most likely a bug in PyInstaller. But it would be good to
ask them what they think. (We could potentially adjust NumPy to make it
robust to this behavior, but that might hide other bugs where docstrings
are dropped by mistake.)
…On Tue, Apr 16, 2019 at 3:31 AM bv-research ***@***.***> wrote:
After some deeper checking, building and comparing with NumPy 1.15 build
it seems that PyInstaller passes the Py_OptimizeFlag correctly when it
freeze the code.
*BUT* the output bundle *do not store* the flag state when it was
generated.
The generated bundle will have the sys.frozen=True attribute with
sys.flags.optimize=0 this is why Py_RETURN_NONE is not returned as
Py_OptimizeFlag state was not saved.
https://github.com/numpy/numpy/blob/ca8a22cdaf23ae698db26d1748b3a330dae7b7da/numpy/core/src/multiarray/compiled_base.c#L1412-L1415
As i see it (i may be wrong) array_function_from_dispatch may be called
when no docstrings are available such the above case, thus it breaks the
docs_from_dispatcher=True logic.
i'm not sure how to continue from here, is this something that needed to
be handled in NumPy or PyInstaller?
For my scenario this next code did the job without doing changes to NumPy
core files:
# added in the main module before import numpyimport sysif __doc__ is None and hasattr(sys, 'frozen'):
from ctypes import c_int, pythonapi
c_int.in_dll(pythonapi, 'Py_OptimizeFlag').value = 2
or more generic:
def frozen_oo():
"""Check if code is frozen with optimization=2"""
import sys
if frozen_oo.__doc__ is None and hasattr(sys, 'frozen'):
from ctypes import c_int, pythonapi
c_int.in_dll(pythonapi, 'Py_OptimizeFlag').value = 2
frozen_oo()import numpy as np...
—
You are receiving this because you were mentioned.
Reply to this email directly, view it on GitHub
<#13248 (comment)>, or mute
the thread
<https://github.com/notifications/unsubscribe-auth/ABKS1txvPvB2iuLuVGzc3F6TZ4TY8rMIks5vhaZ8gaJpZM4cYFfp>
.
|
and cx_freeze |
And Buildozer when making Android package |
Discarding the docstrings results in an error when using numpy and pyinstaller. numpy/numpy#13248
I am running into the same issue using WiX Toolset to create Windows installers when using the |
I encountered this issue using cx_Freeze. What happens is that cx_Freeze packages .pyc-files only, not including the original .py-files. If the .pyc-files are created using -OO, but are run without -OO, then this is what happens: Docstrings are gone, but the flag that tells Python to remove the docstrings is no longer set. This can be reproduced without either of cx_Freeze, PyInstaller or WiX toolset, by replacing (e.g.) multiarray.py in numpy.core with a file multiarray.pyc that is a copy of multiarray.cpython-38.opt-2.pyc. Whether you see this as is a bug in the freezers or in numpy is a matter of taste; you can argue for both. Python has always supported using .pyc-files in place of .py-files, but that doesn't mean numpy necessarily has to support this aspect of Python. I would appreciate if it did, though. |
Skimming https://www.python.org/dev/peps/pep-0488/, it seems that
Optimized pyc files must be saved with a So this is a bug in the freezer. |
You are quoting a paragraph about the state of affairs prior to PEP 488. Nowadays, all compiled bytecode files are called .pyc, regardless of optimisation level. See the section https://www.python.org/dev/peps/pep-0488/#compatibility-considerations. The interpreter does not recognise cache file names like |
Not as I read it - the state of affairs prior to PEP 488 was to have |
Correct, and this is a feature. The interpreter only recognizes these files if launched with |
The interpreter recognises neither of |
Apologies, your link above was broken and I didn't notice. I've edited it to work, and read it now. Is there anywhere I can read up on bytecode-only deployments? I assume you can't just distribute a |
Ah, PEP 3147 has this to say:
|
Presumably this whole problem can be reduced to: # foo.pyc
""" this docstring may be optimized out""" # bar.py
import sys
import foo
if sys.flags.optimize < 2:
assert foo.__doc__ and compiling / running with different optimization levels. If so, I suggest you open an issue with PyInstaller asking what the expected behavior is and why. |
Exactly. Numpy makes the assumption that all bytecode executed has been compiled with the current value of sys.flags.optimize. When this assumption does not hold, numpy fails. CPython supports mixed-optimisation execution, numpy does not. There are no special rules for bytecode-only deployments. Any module can be implemented with a |
I'm not at all convinced this is deliberate. Here's what I consider the minimal case: """
This file will succeed if imported from a .opt-n.pyc file in __pycache__, but
fail if run from a manually created `.pyc` compiled at a different optimization
level to the interpreter that runs it. Is this second use-case an invalid use of pyc files?
"""
import sys
if __doc__:
assert sys.flags.optimize in (0, 1)
else:
assert sys.flags.optimize == 2
if __debug__:
assert sys.flags.optimize == 0
else:
assert sys.flags.optimize in (1, 2) The question is, does cpython consider use-cases when this program fails valid? @brettcannon, as the author of PEP 488, do you have any thoughts here, or suggestions of a better place to direct this question? |
Do we have any reason to not just make a numpy/numpy/core/src/multiarray/compiled_base.c Lines 1430 to 1437 in 117b3f4
Although it is unclear to me whether some related tests might fail in such an environment (whether that should exist or not). EDIT: The argument parsing code is just below that |
CPython assumes that the bytecode you are importing was compiled at the same level as the interpreter running. Mixing stuff is just asking for trouble. |
Of course. But it has never been disallowed that I know of, it's been possible to do for at least two decades. Maybe it should be explicitly disallowed, with the interpreter rejecting bytecode with the wrong flag set internally. That certainly would put the pressure on to fix marcelotduarte/cx_Freeze#84 and related issues. Note that cx_Freeze doesn't actually mix stuff - all the .pyc's are consistently optimised to the same level, it's just that the stub program hardwires Py_OptimizeFlag==0. Why that's seemingly so hard to change I don't know. |
@AndersMunch that would require a change to the Honestly, this is the first time anyone has asked me since I wrote importlib back when I was still working on my PhD about this, so I don't think it's worth the hassle to explicitly prevent this. Python is a language of consenting adults, so my answer is simply, "don't do that if you know what's good for you" 😉 . |
Still we need to this manual work around :-( |
My temporary solution is: pip install 'numpy<1.16' |
Still an issue with CPython 3.10.8, cx-Freeze 6.12.0, numpy 1.23.4 on Windows 10 amd64. |
Issue #10167 proposes to refactor docstrings and |
As @brettcannon indicated, the issue is related to compiling at one optimization and running the interpreter at another. A simple solution on the PyInstaller side is to ensure both Analysis and EXE are given the same optimization level. If you are running Pyinstaller on the command line, you would use the --optimize 2 flag described here: If you are using a spec file, it would look something like this, noting that ('O', None, 'OPTION') is given twice to EXE in the options:
|
Uh oh!
There was an error while loading. Please reload this page.
Using PyInstaller with Python optimization flag -OO (which additionally removes docstrings) crashes while importing numpy package.
While running generated executable file the next error shows up:
TypeError: add_docstring() argument 2 must be str, not None
The current implementation is:
numpy/numpy/core/overrides.py
Lines 160 to 168 in d89c4c7
By default
docs_from_dispatcher
isTrue
, due to the optimization flag thedispatcher
will have no docstrings.dispatcher.__doc__
will beNone
numpy/numpy/core/overrides.py
Lines 143 to 144 in d89c4c7
Reproducing code example:
Running PyInstaller
Error message:
Numpy/Python version information:
Numpy/Python version information:
1.16.2 3.7.3 (v3.7.3:ef4ec6ed12, Mar 25 2019, 22:22:05) [MSC v.1916 64 bit (AMD64)]
Other modules version information:
PyInstaller==3.4
System information:
Windows 10.0.16299
The text was updated successfully, but these errors were encountered: