pyinstaller-hooks-contrib
pyinstaller-hooks-contrib copied to clipboard
can't find torchtext dylib files
Pyinstaller builds successfully, however when I run the exe I get an error related to missing torchtext dylib files.
I get the following warnings during the freezing:
98346 WARNING: Cannot find path ./libc++.1.dylib (needed by .../env/lib/python3.9/site-packages/torchtext/_torchtext.so)
98346 WARNING: Cannot find path ./libtorch_python.dylib (needed by .../env/lib/python3.9/site-packages/torchtext/_torchtext.so)
98346 WARNING: Cannot find path ./libtorch.dylib (needed by .../env/lib/python3.9/site-packages/torchtext/_torchtext.so)
98346 WARNING: Cannot find path ./libtorch_cpu.dylib (needed by .../env/lib/python3.9/site-packages/torchtext/_torchtext.so)
98347 WARNING: Cannot find path ./libc10.dylib (needed by .../env/lib/python3.9/site-packages/torchtext/_torchtext.so)
I can find the last 4 dylib files (except libc++.1.dylib
) in my env/torch module and can copy them manually to the dist folder but that doesn't seem like a good workaround and I still can't find libc++.1.dylib
. Updating path / binaries in .spec file doesn't help.
Any ideas on how to resolve this?
- Output of
pyinstaller --version
:4.8
- Version of Python:
3.9
- torchtext:
0.11.2
- torch:
1.10.2
- Platform:
MacOS 12.1
--> - How you installed Python: python.org
It's in site-packages/torchvision/.dylibs/libc++.1.0.dylib
.
That said, those warnings are result of our dependency scanner lacking support for proper interpretation of rpaths, and are often just warnings. Those libraries may end up collected anyway, due to other dependency chains.
In fact, trying to freeze a simple import torchtext
program, I think the problem is that torch dylibs are collected twice, once in application's top level directory (due to dependency analysis) and once in torch/lib
(due to brute-force hook), and this duplication causes a crash. The only way to get the program working is to replace the libraries in top-level directory with symbolic links:
-
libc10.dylib -> torch/lib/libc10.dylib
-
libtorch.dylib -> torch/lib/libtorch.dylib
-
libtorch_cpu.dylib -> torch/lib/libtorch_cpu.dylib
-
libtorch_global_deps.dylib -> torch/lib/libtorch_global_deps.dylib
-
libtorch_python.dylib -> torch/lib/libtorch_python.dylib
this works, thank you!
Romk,
Can you please explain further your comment : " The only way to get the program working is to replace the libraries in top-level directory with symbolic links"
What top-level directory?
I am asking because I think I'm seeing the same problem. When I run pyinstaller I see the following warnings:
37358 WARNING: Cannot find path ./libtorch_cpu.dylib (needed by /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/_torchaudio.so) 37358 WARNING: Cannot find path ./libtorchaudio.so (needed by /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/_torchaudio.so) 37358 WARNING: Cannot find path ./libc10.dylib (needed by /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/_torchaudio.so) 37358 WARNING: Cannot find path ./libtorch_python.dylib (needed by /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/_torchaudio.so) 37358 WARNING: Cannot find path ./libtorch.dylib (needed by /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/_torchaudio.so)
Then when I run the code I get the following messages:
[53127] WARNING: file already exists but should not: /var/folders/95/mfn5xj2s59jgjjch0b8f5jbw0000gn/T/_MEI8pNwtp/torch/_C.cpython-38-darwin.so [53127] WARNING: file already exists but should not: /var/folders/95/mfn5xj2s59jgjjch0b8f5jbw0000gn/T/_MEI8pNwtp/torch/_dl.cpython-38-darwin.so
and:
ImportError: dlopen(/var/folders/95/mfn5xj2s59jgjjch0b8f5jbw0000gn/T/_MEI8pNwtp/torchaudio/_torchaudio.so, 2): Library not loaded: @loader_path/../libtorchaudio.so Referenced from: /private/var/folders/95/mfn5xj2s59jgjjch0b8f5jbw0000gn/T/_MEI8pNwtp/torchaudio/_torchaudio.so
What top-level directory?
Top-level application directory of a onedir
build.
I think I'm not understanding something as it's still not working. (same missing dylib errrors)
(I am actually trying a onefile build, but did test a onedir build with the same results)
I am running pyinstaller from the same directory where I created the linked files.
f01898e9b5db0000:SD_Release-2022_02_25-09_49 user$ ls -al
total 12872
....deleted some files for clarity ....
-rw-r--r-- 1 rpm staff 305 Feb 25 09:49 Run_SD.py
lrwxr-xr-x 1 rpm staff 83 Feb 26 10:12 libc10.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libc10.dylib
lrwxr-xr-x 1 rpm staff 85 Feb 26 10:12 libtorch.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libtorch.dylib
lrwxr-xr-x 1 rpm staff 89 Feb 26 10:25 libtorch_cpu.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libtorch_cpu.dylib
lrwxr-xr-x 1 rpm staff 92 Feb 26 10:12 libtorch_python.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libtorch_python.dylib
lrwxr-xr-x 1 rpm staff 92 Feb 26 10:10 libtorchaudio.so -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/lib/libtorchaudio.so
drwxr-xr-x 7 rpm staff 224 Feb 25 09:49 snakers4_silero-vad_master
f01898e9b5db0000:SD_Release-2022_02_25-09_49 rpm$
And here is the pyinstaller command:
pyinstaller --paths='/Users/rpm/.pyenv/versions/3.8.8/Python.framework/Versions/3.8/lib/python3.8/site-packages/' --paths='/Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/' --hidden-import torch --hidden-import torchaudio --hidden-import platform --hidden-import msgpack --hidden-import ipaddress --hidden-import wave --hidden-import sounddevice --hidden-import soundfile --hidden-import Logger --hidden-import Load_config --hidden-import Smart_Device --hidden-import Audio_Sender --hidden-import json --hidden-import websockets --hidden-import websockets.legacy --hidden-import websockets.legacy.client --hidden-import websockets.legacy.server --hidden-import signal --hidden-import asyncio --clean --osx-bundle-identifier com.myprogram.SD --add-data ./snakers4_silero-vad_master:./snakers4_silero-vad_master --add-data *.bin:./ --add-data Sconfig.json:./ --onefile Run_SD.py
--paths='/Users/rpm/.pyenv/versions/3.8.8/Python.framework/Versions/3.8/lib/python3.8/site-packages/' --paths='/Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/'
If you find yourself adding your python's site-packages to search path, you're likely doing something wrong. If it actually solves some kind of problem, then you either have not activated your virtual environment, or you have installed PyInstaller in an environment that is different from your target virtual environment.
In either case, you're not going to be in for a pleasant experience - better sort out your environments before trying anything else.
--hidden-import torch --hidden-import torchaudio --hidden-import platform --hidden-import msgpack --hidden-import ipaddress --hidden-import wave --hidden-import sounddevice --hidden-import soundfile --hidden-import Logger --hidden-import Load_config --hidden-import Smart_Device --hidden-import Audio_Sender --hidden-import json --hidden-import websockets --hidden-import websockets.legacy --hidden-import websockets.legacy.client --hidden-import websockets.legacy.server --hidden-import signal --hidden-import asyncio
Are these really necessary?
--onefile
Don't use onefile until you have a onedir build up and running. The latter is much easier to debug in terms of checking for missing files.
-rw-r--r-- 1 rpm staff 305 Feb 25 09:49 Run_SD.py lrwxr-xr-x 1 rpm staff 83 Feb 26 10:12 libc10.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libc10.dylib lrwxr-xr-x 1 rpm staff 85 Feb 26 10:12 libtorch.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libtorch.dylib lrwxr-xr-x 1 rpm staff 89 Feb 26 10:25 libtorch_cpu.dylib -> /Users/rpm/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torch/lib/libtorch_cpu.dylib
Just for the record, these symlinks are not what we were discussing earlier in this thread. We were talking about manually modifying the generated onedir
dist directory, and replacing the duplicated .dylibs with symlinks to work around PyInstaller's shortcomings w.r.t. torch on macOS.
The error you were getting,
ImportError: dlopen(/var/folders/95/mfn5xj2s59jgjjch0b8f5jbw0000gn/T/_MEI8pNwtp/torchaudio/_torchaudio.so, 2): Library not loaded: @loader_path/../libtorchaudio.so Referenced from: /private/var/folders/95/mfn5xj2s59jgjjch0b8f5jbw0000gn/T/_MEI8pNwtp/torchaudio/_torchaudio.so
indicates that libtorchaudio.so
is missing from the top-level frozen application's directory, so either it is not collected at all, or it is collected in a "wrong" directory (e.g., its original sub-directory, whereas PyInstaller's path rewriting expects it to be in the top-level directory).
Create a onedir build and check what the actual situation is.
(Although it is likely that torchaudio
libs also reference the torch
libs, so you'll end up with the same problem as was originally discussed here in the context of torchtext
. But currently, you're probably hitting a different problem with that missing libtorchaudio.so
).
- I've removed the --paths and it is working (was added along time ago and things have changed since).
- I tried removing the --hidden-imports and I get an error when I try to run the program ( ModuleNotFoundError: No module named 'ipaddress' ). This is the same error I was getting for each module and was fixed by adding them is as hidden-imports.
- Removing the --hidden-imports for torch and torchauido does get rid of the error message about the .dylibs, but when I run it complains ( ModuleNotFoundError: No module named 'torch' )
- If I keep the --hidden-imports I get the missing dylib warnings, but are in the onedir directory. On the other hand libtorchaudio.so is missing, and as expected when I try to run the program it complains that it is missing. (Note: running my program does work as expected when using python RunSD.py)
- If I copy the so into the dist directory and try to run the program I get a pile of errors:
libc++abi.dylib: terminating with uncaught exception of type c10::Error: Type c10::intrusive_ptr<ConvPackedParamsBase<2>, c10::detail::intrusive_target_default_null_type<ConvPackedParamsBase<2> > > could not be converted to any of the known types. Exception raised from operator() at ../aten/src/ATen/core/jit_type.h:1674 (most recent call first): frame #0: c10::Error::Error(c10::SourceLocation, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> >) + 98 (0x142383522 in libc10.dylib) frame #1: c10::detail::torchCheckFail(char const*, char const*, unsigned int, std::__1::basic_string<char, std::__1::char_traits<char>, std::__1::allocator<char> > const&) + 106 (0x142381c3a in libc10.dylib) frame #2: c10::detail::getTypePtr_<c10::intrusive_ptr<ConvPackedParamsBase<2>, c10::detail::intrusive_target_default_null_type<ConvPackedParamsBase<2> > > >::call()::'lambda'()::operator()() const + 260 (0x12c45dd34 in libtorch_cpu.dylib)
Any further suggestions?
If I copy the so into the dist directory and try to run the program I get a pile of errors:
This pile of errors is probably due to duplicated copies, as was discussed before in this thread. So you'll need to replace the copies in top-level directory with symlinks to the copies in corresponding sub-directories. This goes for the torch dylibs that I listed earlier in https://github.com/pyinstaller/pyinstaller-hooks-contrib/issues/375#issuecomment-1025913127, but may also apply to the libtorchaudio.so
if another copy was collected in the corresponding sub-directory.
Thanks - I now have a onedir build that is able to run!
After running pyinstaller I needed to:
- Delete from the base onedir directory and link the following:
rm libtorch_python.dylib
rm libtorch.dylib
rm libc10.dylib
rm libtorch_cpu.dylib
ln -s ./torch/lib/libtorch_python.dylib libtorch_python.dylib
ln -s ./torch/lib/libtorch.dylib libtorch.dylib
ln -s ./torch/lib/libc10.dylib libc10.dylib
ln -s ./torch/lib/libtorch_cpu.dylib libtorch_cpu.dylib
- Copy across libtorchaudio.so
cp ~/.pyenv/versions/3.8.8/lib/python3.8/site-packages/torchaudio/lib/libtorchaudio.so .
Now that this is running, how do I make these same changes with a onefile build???
Now that this is running, how do I make these same changes with a onefile build???
Since PyInstaller does not support symlinks in a onefile build, the only way to make this work in a onefile build at the moment is to perform these cleanup steps at the beginning of your python program.
EDIT: and the missing libtorchaudio.so
can be collected via --add-binary
command-line option.
Thanks so much - I now have it fully working as a single file distribution !
Your responsiveness has been amazing.
I also encountered this. I found that there is no hook for torchaudio but only for torch and torchvision. The hook for torch is very simple: datas = [(get_module_paths('torch')[1], 'torch'), ]
. So I made a same hook-torchaudio.py
: datas = [(get_module_paths('torchaudio')[1], 'torch'), ]
. But it still tells:
1513 WARNING: Cannot find path ./libc10.dylib (needed by /Users/rosa/miniconda3/envs/DemucsPack/lib/python3.9/site-packages/torchaudio/_torchaudio.so)
1513 WARNING: Cannot find path ./libtorchaudio.so (needed by /Users/rosa/miniconda3/envs/DemucsPack/lib/python3.9/site-packages/torchaudio/_torchaudio.so)
1513 WARNING: Cannot find path ./libtorch_python.dylib (needed by /Users/rosa/miniconda3/envs/DemucsPack/lib/python3.9/site-packages/torchaudio/_torchaudio.so)
1513 WARNING: Cannot find path ./libtorch.dylib (needed by /Users/rosa/miniconda3/envs/DemucsPack/lib/python3.9/site-packages/torchaudio/_torchaudio.so)
1513 WARNING: Cannot find path ./libtorch_cpu.dylib (needed by /Users/rosa/miniconda3/envs/DemucsPack/lib/python3.9/site-packages/torchaudio/_torchaudio.so)
But all those binaries are packed. And when I run the program, I got this error:
pyimod04_ctypes.install.<locals>.PyInstallerImportError: Failed to load dynlib/dll '.../torchaudio/lib/libtorchaudio.so'. Most likely this dynlib/dll was not found when the application was frozen.
Sometimes it is not the error above:
ImportError: dlopen(.../torchaudio/_torchaudio.so, 2): Library not loaded: @loader_path/../libtorchaudio.so
Referenced from: .../torchaudio/_torchaudio.so
Reason: image not found
I tried to use otool and found the copied binary is different from the oringinal:
./lib/python3.9/site-packages/torchaudio/_torchaudio.so:
@rpath/_torchaudio.so (compatibility version 0.0.0, current version 0.0.0)
@rpath/libtorchaudio.so (compatibility version 0.0.0, current version 0.0.0)
@rpath/libtorch_python.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libtorch.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libtorch_cpu.dylib (compatibility version 0.0.0, current version 0.0.0)
@rpath/libc10.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 902.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
./dist/Test/torchaudio/_torchaudio.so:
@loader_path/../_torchaudio.so (compatibility version 0.0.0, current version 0.0.0)
@loader_path/../libtorchaudio.so (compatibility version 0.0.0, current version 0.0.0)
@loader_path/../libtorch_python.dylib (compatibility version 0.0.0, current version 0.0.0)
@loader_path/../libtorch.dylib (compatibility version 0.0.0, current version 0.0.0)
@loader_path/../libtorch_cpu.dylib (compatibility version 0.0.0, current version 0.0.0)
@loader_path/../libc10.dylib (compatibility version 0.0.0, current version 0.0.0)
/usr/lib/libc++.1.dylib (compatibility version 1.0.0, current version 902.1.0)
/usr/lib/libSystem.B.dylib (compatibility version 1.0.0, current version 1281.100.1)
The error is same when I use --add-binary
and --exclude-module torchaudio
instead of self-made hook.
I can't copy them after the build is finished, because I need a .app
file. Copying manually will cause the signature to fail.
I can't copy them after the build is finished, because I need a
.app
file. Copying manually will cause the signature to fail.
You can modify the generated .app bundle and then re-sign it manually...
Is there a similar workaround (for either the onedir
or the onefile
solution) for packaging on Windows where the ability to create symlinks isn't available to the average user?
Is there a similar workaround (for either the
onedir
or theonefile
solution) for packaging on Windows where the ability to create symlinks isn't available to the average user?
This issue and its work-around are macOS-specific, so no. If you have problems on Windows, open a new issue and provide the error traceback (as well as python and pyinstaller version), so we can see what's going on.
Still having this issue with torch 1.12.1, pyinstaller 5.6.2 and pyinstaller-hooks-contrib 2022.13:
pyimod03_ctypes.install.<locals>.PyInstallerImportError: Failed to load dynlib/dll '/.../dist/.../libtorch_global_deps.dylib'. Most likely this dynlib/dll was not found when the application was frozen.
I added the symlinks, but the error stays the same.
I deleted the libs and symlinks in the top folder, same issue. I deleted the lib folder in pytorch in the onedir, same issue. Not sure what else to do, does anyone have an idea?
Still having this issue with torch 1.12.1, pyinstaller 5.6.2 and pyinstaller-hooks-contrib 2022.13:
pyimod03_ctypes.install.<locals>.PyInstallerImportError: Failed to load dynlib/dll '/.../dist/.../libtorch_global_deps.dylib'. Most likely this dynlib/dll was not found when the application was frozen.
I added the symlinks, but the error stays the same.
I deleted the libs and symlinks in the top folder, same issue. I deleted the lib folder in pytorch in the onedir, same issue. Not sure what else to do, does anyone have an idea?
When you were creating symlinks and removing libs, did you actually see libtorch_global_deps.dylib
among the collected files? Because the error implies that the shared library was not collected in the first place, which is different from the issue that we were working-around here...
That said, if I freeze a simple import torch
program, the libtorch_global_deps.dylib
is collected by the hook into its original location, torch/lib/libtorch_global_deps.dylib
(and it seems to be discovered there via ctypes). Can you check if it was collected there in your case? If not, how did you install torch - pip, conda, ...? Also, can we see the whole error traceback, so we can see where the ctypes import attempt originated from?
Sure, I actually made a test with a new environment, so let me share it with you:
I created a conda env with only pyinstaller and pytorch. I used conda to install pytorch, with:
conda install pytorch torchvision torchaudio -c pytorch
Then I wrote a simple script, that runs correctly:
import torch
dev = torch.device("cuda") if torch.cuda.is_available() else torch.device("cpu")
print(dev)
Then, I just ran pyinstaller with its default settings:
pyinstaller Pyinstaller_pytorch.py
And this is the full error I have:
Traceback (most recent call last):
File "PyInstaller/loader/pyimod03_ctypes.py", line 53, in __init__
File "ctypes/__init__.py", line 374, in __init__
OSError: dlopen(/Users/adrienlefalher/Dropbox/PYCHARM/pyinstaller_test/dist/Pyinstaller_pytorch/torch/lib/libtorch_global_deps.dylib, 10): Library not loaded: @rpath/libmkl_intel_lp64.dylib
Referenced from: /Users/adrienlefalher/Dropbox/PYCHARM/pyinstaller_test/dist/Pyinstaller_pytorch/torch/lib/libtorch_global_deps.dylib
Reason: image not found
The above exception was the direct cause of the following exception:
Traceback (most recent call last):
File "Pyinstaller_pytorch.py", line 1, in <module>
File "<frozen importlib._bootstrap>", line 1007, in _find_and_load
File "<frozen importlib._bootstrap>", line 986, in _find_and_load_unlocked
File "<frozen importlib._bootstrap>", line 680, in _load_unlocked
File "PyInstaller/loader/pyimod02_importers.py", line 499, in exec_module
File "torch/__init__.py", line 191, in <module>
_load_global_deps()
File "torch/__init__.py", line 153, in _load_global_deps
ctypes.CDLL(lib_path, mode=ctypes.RTLD_GLOBAL)
File "PyInstaller/loader/pyimod03_ctypes.py", line 55, in __init__
pyimod03_ctypes.install.<locals>.PyInstallerImportError: Failed to load dynlib/dll '/Users/adrienlefalher/Dropbox/PYCHARM/pyinstaller_test/dist/Pyinstaller_pytorch/torch/lib/libtorch_global_deps.dylib'. Most likely this dynlib/dll was not found when the application was frozen.
[95460] Failed to execute script 'Pyinstaller_pytorch' due to unhandled exception!
It did collect the libs in pytorch/lib:
libc10.dylib libshm.dylib libtorch_cpu.dylib libtorch_global_deps.dylib libtorch_python.dylib libtorch.dylib
And in the "base" directory, I also have the mkl libs:
libmkl_intel_ilp64.1.dylib libmkl_intel_ilp64.dylib libmkl_intel_lp64.1.dylib libmkl_intel_lp64.dylib libmkl_intel_thread.1.dylib libmkl_intel_thread.dylib
So first, unless you absolutely have to use Anaconda, I suggest you to switch to python.org python + pip-installed packages when building with PyInstaller - because in addition to spotty Anaconda support (on top of already less-than-ideal torch support), you'll also end up with bloated builds, because we don't handle symlinks correctly, and so versioned dylibs collected from anaconda installation will end up as separate copies (instead of a single copy and symlinks).
Back to the issue, though: the problem is that torch/lib/libtorch_global_deps.dylib
cannot find its dependency, libmkl_intel_lp64.dylib
, which was originally discoverable via rpath
, but this now points to incorrect directory due to relative paths being changed w.r.t. to original installation layout.
This can be fixed by manually adjusting the rpath to point to correct directory:
install_name_tool -rpath @loader_path/../../../../ @loader_path/../.. dist/<program>/torch/lib/libtorch_global_deps.dylib
Unfortunately, that's not the only lib with such problem. libmkl_intel_lp64.dylib
also won't be able to find libiomp5.dylib
; this time, because rpath
is not set (and is probably inherited, but those inherited paths don't point to the correct location). The fix is to explicitly add rpath that points to the correct location (= @loader_path, i.e., the same directory as the library on which we are setting the rpath):
install_name_tool -add_rpath @loader_path dist/program/libmkl_intel_lp64.dylib
install_name_tool -add_rpath @loader_path dist/program/libmkl_intel_thread.1.dylib
(and so on for any other MKL library that has problem finding libiomp5.dylib
).
Changing/adding rpath invalidates the signature (even if it is just ad-hoc one), so you might need to re-sign the modified libraries as well. If you did not use signing identity with PyInstaller, then you can just re-sing with ad-hoc identity, which is what PyInstaller uses by default.
As per your instructions, I recreated the environment with pip. However, I still have an issue with torchvision. I could create a new issue for it, but I wanted to show it to you here:
torchvision/io/image.py:13: UserWarning: Failed to load image Python extension:
Traceback (most recent call last):
File "src/__main__.py", line 3, in <module>
File "src/initialisation/initialisation.py", line 10, in <module>
File "src/front/remi_interface.py", line 17, in <module>
File "src/front/IconoController.py", line 19, in <module>
File "src/algorithms/ImagesToEmbeddings.py", line 13, in <module>
File "src_model/Model.py", line 11, in <module>
File "torchvision/__init__.py", line 5, in <module>
File "torchvision/models/__init__.py", line 3, in <module>
File "torchvision/models/densenet.py", line 32, in <module>
File "torchvision/models/densenet.py", line 68, in _DenseLayer
File "/Users/.../torch/_jit_internal.py", line 915, in _overload_method
_check_overload_body(func)
File "/Users/.../torch/_jit_internal.py", line 835, in _check_overload_body
parsed_def = parse_def(func)
File "/Users/.../torch/_sources.py", line 122, in parse_def
sourcelines, file_lineno, filename = get_source_lines_and_file(
File "/Users/.../torch/_sources.py", line 23, in get_source_lines_and_file
sourcelines, file_lineno = inspect.getsourcelines(obj)
File "inspect.py", line 1006, in getsourcelines
File "inspect.py", line 831, in findsource
File "linecache.py", line 46, in getlines
File "linecache.py", line 137, in updatecache
File "codecs.py", line 322, in decode
UnicodeDecodeError: 'utf-8' codec can't decode byte 0xe3 in position 16: invalid continuation byte
I found on stackoverflow to change the compat.py file in pyinstaller and replaced
out = out.decode(encoding)
with
out = out.decode(encoding, errors='ignore')
however, it doesn't look like a great solution, and doesn't solve the issue anyway.
This looks like an encoding problem with the source file that's required by torch's JIT. Based on the traceback, I think it should be torchvision/models/densenet.py
.
Has this file been collected by PyInstaller (since we typically do not collect sources, and we do not have a torchvision
hook that would force collection, unlike for base torch
). If the file is collected, can you run diff against the original torchvision/models/densenet.py
from your venv, and see if there is any difference? Or perhaps, if you try to replace the collected file with a fresh manual copy, does this fix the problem?
I only have the .pyc file in torchvision in the pyinstaller, so it has not been collected. Copy pasting the original torchvision folder into the pyinstaller torchvision folder then gives me this error at runtime:
/Users/adrienlefalher/Dropbox/PYCHARM/ICONO/dist/ICONO/torchvision/io/image.py:13: UserWarning: Failed to load image Python extension: Failed to load dynlib/dll '/Users/adrienlefalher/Dropbox/PYCHARM/ICONO/dist/ICONO/torchvision/image.so'. Most likely this dynlib/dll was not found when the application was frozen.
warn(f"Failed to load image Python extension: {e}")
I really appreciate all your swift help, thank you.
I only have the .pyc file in torchvision in the pyinstaller, so it has not been collected.
Are you building with --debug noarchive
or --debug all
? If not, the .pyc files should be collected into the executable-embedded archive and not as individual files...
Copy pasting the original torchvision folder into the pyinstaller torchvision folder then gives me this error at runtime:
/Users/adrienlefalher/Dropbox/PYCHARM/ICONO/dist/ICONO/torchvision/io/image.py:13: UserWarning: Failed to load image Python extension: Failed to load dynlib/dll '/Users/adrienlefalher/Dropbox/PYCHARM/ICONO/dist/ICONO/torchvision/image.so'. Most likely this dynlib/dll was not found when the application was frozen. warn(f"Failed to load image Python extension: {e}")
Like before, there was likely more to that error than only last line (e.g., missing dependency).
If you copied the whole torchvision folder, you probably overwrote the shared libraries that PyInstaller processed. Instead of manual copying, can you try adding --collect-all torchvision
to your PyInstaller command (we usually discourage use of this one, but it's the quickest way to ensure that source .py files are collected...).
Rebuilding the env with venv instead of conda and using --collect-all torchvision
solved my issue :) Thanks!
I had the same problem, and I solved it by rm & ln -s the dylibs in the torch. I want to onefile because onedir solved.
Since PyInstaller does not support symlinks in a onefile build, the only way to make this work in a onefile build at the moment is to perform these cleanup steps at the beginning of your python program.
How can I do this exactly? Which option should I use?
Since PyInstaller does not support symlinks in a onefile build, the only way to make this work in a onefile build at the moment is to perform these cleanup steps at the beginning of your python program.
How can I do this exactly? Which option should I use?
There's no option for this. You need to implement the required steps in your python code, at the start of your program (using os.remove
, os.symlink
, etc.).
I have written code like this.
import os
import stanza
import sys
for filename in sorted(os.listdir('.')):
print(f"check {filename}")
For --onedir, os.remove and os.symlink are possible. And segmentfaults could be resolved.
$ pyinstaller main.py --onedir
$ cd dist/main
$ ./main
check PIL
check base_library.zip
check certifi
check charset_normalizer
check google
check lib-dynload
check libXau.6.0.0.dylib
check libbrotlicommon.1.0.9.dylib
(snip)
In --onefile how can I find the following files?
- libc10.dylib
- libshm.dylib
- libtorch_cpu.dylib
- libtorch_global_deps.dylib
- libtorch_python.dylib
- libtorch.dylib
$ pyinstaller main.py --onefile
$ cd dist/main
$ ./main
check main
for filename in sorted(os.listdir('.')):
Instead of using '.'
, which assumes that your application directory is your current working directory (which is never true for onefile
, and not necessarily true for onedir
, either), you should either use os.path.dirname(__file__)
or sys._MEIPASS
, as described in docs.
Wow, it worked. Thank you very much.
Has this issue been fixed since torch and torchaudio, torchtext 2.0 has been released? I'm no longer using macOS, but I had to manually copy the missing DLLs on Windows when I encountered this problem on macOS. I have just tested again, and my Windows application functions well without any further operation after packing with PyInstaller, so I guess that the issue will also be fixed once pytorch (and other torch utilities) is updated to 2.0
Can anybody try that?