# Solution about python module "tabula" runs successfully but fails in .exe
Solution about python module tabula runs .py successfully and use pyinstaller to build .exe but the .exe will execute fail.
Environment
---
- python : 3.7
- pyinstaller : 5.9.0
- tabula-py : 2.9.0
Happens
---
### Preparation
1. `pip3 installer tabula-py`
2. `pip3 list`

### When I want to use tabula to read pdf file:
#### It can run Success :

`py -3.7 compare_BCU_RN.py`

#### and Build .exe Success :
`pyinstaller -F compare_BCU_RN.py`

> Also don't have any warning or error in build/warn.txt and build/xerf.html
#### BUT it will run FAIL ! :
Run .exe (double click/power shell/cmd).

Root Cause
---
Module tubalu is Java base and made for running on OS(JVM).
> ...
*Tabula allows you to extract that data in CSV format, through a simple web interface.*
...
Therefore, it does not consider supporting source code (python module source code) for being built into exe by pyinstaller.
It means that it actually just uses python-command to execute Tabula-Java.
> You can refer to tabula-py/tabula/io.py
This is the result of the error you saw when executing exe in powershell in the previous picture.
#### Official link
- [OpenNews Source](https://source.opennews.org/articles/introducing-tabula/)
- [Tabula Github](https://github.com/tabulapdf/tabula)
- [Download from the official site](https://tabula.technology/)
Solution
---
:::info
Notice : Just install java CANNOT fix this error.
But if you want to run in python script, install and check path is fine
:::
Let the .spec(pyinstaller actually build spec, refer "知呼-Pyinstaller打包通用流程" under) to pack "tabula" data file.
### General :
1. Run ```pyinstaller -F {your}.py```
2. Modify {your}.spec :
* Add ```from PyInstaller.utils.hooks import collect_data_files```
* Modify ```datas=[],```to ```datas=collect_data_files("tabula"),```
* As line 2 and 9 
3. Run ```python pyinstaller {your}.spec```
:::info
Notice : Is .spec instead of .py
:::
### Practical :
It will take a lot of time if you have to manually modify it every time.
So you can use my .bat script:
```bat
REM Build first
pyinstaller -F {YOUR}.py
echo MOD .spec START!!
@echo off
setlocal enabledelayedexpansion
REM 1. copy {YOUR}.spec to {YOUR}_ori.spec
copy {YOUR}.spec {YOUR}_ori.spec
set "file={YOUR}.spec"
REM 2. Insert "from PyInstaller.utils.hooks import" in No.2 line of {YOUR}.spec
set "line_number=2"
set "new_line=from PyInstaller.utils.hooks import collect_data_files"
(for /f "tokens=1* delims=:" %%a in ('findstr /n "^" %file%') do (
echo.%%b
if %%a equ %line_number% echo.!new_line!
)) > "%file%.new"
move /y "%file%.new" "%file%"
echo done step 2
REM 3. Change "datas=[]" to "datas=collect_data_files(\"tabula\")"
set "new_line= datas=collect_data_files("tabula"),"
(for /f "delims=" %%a in ('type "%file%"') do (
set "line=%%a"
if "!line!"==" datas=[]," (
echo !new_line!
) else (
echo !line!
)
)) > "%file%.new"
move /y "%file%.new" "%file%"
echo done step 3
echo MOD .spec END!!
REM Build spec only again
pyinstaller {YOUR}.spec
```
You just run this .bat every time after saved {your}.py, remember put it at the same folder with {your}.py.
==Error Fixed !!==
If you don't want to make a new file, maybe you can try this solution :
[stackoverflow-Unable to access jarfile 'tabula-1.0.2-jar-with-dependencies.jar'](https://stackoverflow.com/questions/50544515/unable-to-access-jarfile-tabula-1-0-2-jar-with-dependencies-jar)
Reference
---
- Solution step reference : [Github-Unable to access Jarfile](https://github.com/pyinstaller/pyinstaller/issues/5298)
- pyinstaller flow reference : [知呼-Pyinstaller打包通用流程](https://zhuanlan.zhihu.com/p/165431703)
###### tags: `tabula` `python` `pyinstaller`