Description
Hey guys,
Problem description
I've just discovered that nibabel
2.2.0 is incompatible with both pyinstaller
and py2app
, projects for creating standalone (a.k.a. "frozen") python applications.
Here is a stack trace from a frozen version of FSLeyes using nibabel
2.2.0:
[fsluser@localhost dist]$ ./FSLeyes/fsleyes -V
Traceback (most recent call last):
File "site-packages/wx/core.py", line 3163, in <lambda>
File "fsleyes/main.py", line 203, in init
File "site-packages/nibabel/__init__.py", line 38, in <module>
File "site-packages/nibabel/analyze.py", line 87, in <module>
File "site-packages/nibabel/volumeutils.py", line 22, in <module>
File "site-packages/nibabel/casting.py", line 11, in <module>
File "site-packages/nibabel/testing/__init__.py", line 35, in <module>
File "site-packages/nibabel/testing/np_features.py", line 19, in <module>
File "site-packages/nibabel/testing/np_features.py", line 12, in _memmap_after_ufunc
FileNotFoundError: [Errno 2] No such file or directory: '/home/fsluser/dist/FSLeyes/nibabel/testing/np_features.pyc'
Cause
This occurs because nibabel.testing.np_features
is now imported when the nibabel
package is imported*. The nibabel.testing.np_features._memmap_after_ufunc
function is called on import, and attempts to open the file nibabel/testing/np_features.py
. The catch is that this source file doesn't exist when the code is executed from a frozen application.
* The import in the stack trace above (
nibabel/casting.py
) is, ironically, an unused import. Butnibabel.testing
is explicitly imported innibabel/__init__.py
a little later on, so this error would still occur if the unused imports were removed.
Solutions
First of all, I'm not sure if this should be fixed within nibabel
, or rather if it should be the responsibility of pyinstaller
/py2app
to explicitly handle nibabel
(they have hooks for various other projects, e.g. matplotlib
, numpy
, etc).
Having said that, it would be easy to fix within nibabel
- here are a couple of ideas:
- Open a different file, one which is known to exist
- Test to see if the file exists before opening it. If it doesn't, fall back to a more primitive test (e.g. checking the
numpy
version number)
What do you think? I'm happy to start a PR if you think that this should be handled in nibabel
.