holoviz / datashader

Quickly and accurately render even the largest data.
http://datashader.org
BSD 3-Clause "New" or "Revised" License
3.24k stars 363 forks source link

dsshow not working after converting pyqt5 project into exe using pyinstaller #1268

Closed Karthik-2002-git closed 10 months ago

Karthik-2002-git commented 10 months ago

Thanks for contacting us! Please read and follow these instructions carefully, then delete this introductory text to keep your issue easy to read. Note that the issue tracker is NOT the place for usage questions and technical assistance; post those at Discourse instead. Issues without the required information below may be closed immediately.

ALL software version info

(this library, plus any other relevant software, e.g. bokeh, python, notebook, OS, browser, etc) python - 3.9.13 pyinstaller - 5.13.0 datashader - 0.15.1 qt5-applications - 5.15.2.2.3 qt5-tools - 5.15.2.1.3

Description of expected behavior and the observed behavior

I have converted my pyqt5 project into exe using pyinstaller. The project has alot of library imports and one among that is the 'dshow' function of the 'datashader.mpl_ext' library (used for data visualization). Whenver the converted exe app invokes the dsshow function, it gets crashed. I also tried adding 'datashader.mpl_ext' and 'datashader' in hidden imports, but still the app crashes while calling the dsshow function showing the eroor 'OSerror : source code not found'

Complete, minimal, self-contained example code that reproduces the issue

# code goes here between backticks

Stack traceback and/or browser JavaScript console output

Screenshots or screencasts of the bug in action

dsshow issue

deepsthewarrior commented 10 months ago

I also face the same issue when I try to compile my python script to linux binary using pyinstaller.

minimum code to reproduce the issue

import numpy as np
import pandas as pd
import datashader as ds
import datashader.transfer_functions as tf
from PyQt5.QtWidgets import QApplication, QMainWindow, QLabel
from PyQt5.QtGui import QImage, QPixmap
from PyQt5.QtCore import Qt

class MyApp(QMainWindow):
    def __init__(self):
        super().__init__()

        self.setWindowTitle("PyQt5 App with DataShader")
        self.setGeometry(100, 100, 800, 600)

        canvas = QLabel(self)
        canvas.setGeometry(50, 50, 700, 500)

        # Create random data points for the scatter plot
        np.random.seed(42)
        num_points = 1000
        df = pd.DataFrame({
            'x': np.random.random(num_points) * 100,
            'y': np.random.random(num_points) * 100
        })

        cvs = ds.Canvas(plot_width=700, plot_height=500)
        agg = cvs.points(df, 'x', 'y')
        img = tf.shade(agg, cmap=["blue", "green"], how='eq_hist')

        # Convert DataShader image to QPixmap
        qimg = QImage(img.data, img.shape[1], img.shape[0], QImage.Format_RGBA8888)
        pixmap = QPixmap.fromImage(qimg)
        canvas.setPixmap(pixmap)

if __name__ == "__main__":
    app = QApplication(sys.argv)
    window = MyApp()
    window.show()
    sys.exit(app.exec_())

command i used to compile pyinstaller --onefile test.py

Output

image

However, i could find more missing imports(500+) in the warn-txt file. I also tried with hidden-imports and paths as given below, but in vain.

pyinstaller --onefile --paths=/myenv/lib/python3.10/site-packages/ --hidden-import spatialpandas.geometry file.py

Anyhelp would be much appreciated

ianthomas23 commented 10 months ago

Datashader makes extensive use of numba which uses llvmlite to compile python code on demand to make everything fast. There is a FAQ in the numba docs about using pyinstaller, see https://numba.readthedocs.io/en/stable/user/faq.html#can-i-freeze-an-application-which-uses-numba

ianthomas23 commented 10 months ago

I am closing this as no action is required here.

Karthik-2002-git commented 6 months ago

I am closing this as no action is required here.

Editing the .spec file solved the problem. Added module_collection_mode as the last keyword argument to the Analysis :

a = Analysis( ... module_collection_mode={ 'datashader': 'pyz+py', }, )