From 7537dc45ef993b7490973285743b73bd92570877 Mon Sep 17 00:00:00 2001 From: Devin AI <158243242+devin-ai-integration[bot]@users.noreply.github.com> Date: Tue, 15 Apr 2025 20:56:31 +0000 Subject: [PATCH] Add PyInstaller compatibility support (fixes #2613) Co-Authored-By: Joe Moura --- README.md | 11 +++++++++++ src/crewai/utilities/pyinstaller_compat.py | 12 ++++++++++++ tests/test_pyinstaller_compat.py | 16 ++++++++++++++++ 3 files changed, 39 insertions(+) create mode 100644 src/crewai/utilities/pyinstaller_compat.py create mode 100644 tests/test_pyinstaller_compat.py diff --git a/README.md b/README.md index 5669c71a2..a7b4712da 100644 --- a/README.md +++ b/README.md @@ -440,5 +440,16 @@ A: CrewAI uses anonymous telemetry to collect usage data for improvement purpose ### Q: Where can I find examples of CrewAI in action? A: You can find various real-life examples in the [CrewAI-examples repository](https://github.com/crewAIInc/crewAI-examples), including trip planners, stock analysis tools, and more. +### Q: Can I package my CrewAI application as an executable? +A: Yes, CrewAI is compatible with PyInstaller, which allows you to package your application into a standalone executable. To create an executable: +```shell +# Install PyInstaller +pip install pyinstaller + +# Create the executable +pyinstaller --onefile your_script.py +``` +The generated executable will be in the `dist` directory. + ### Q: How can I contribute to CrewAI? A: Contributions are welcome! You can fork the repository, create a new branch for your feature, add your improvement, and send a pull request. Check the Contribution section in the README for more details. diff --git a/src/crewai/utilities/pyinstaller_compat.py b/src/crewai/utilities/pyinstaller_compat.py new file mode 100644 index 000000000..6b40868e5 --- /dev/null +++ b/src/crewai/utilities/pyinstaller_compat.py @@ -0,0 +1,12 @@ +import os +import sys + +def is_bundled(): + """Check if the application is running from a PyInstaller bundle.""" + return getattr(sys, 'frozen', False) and hasattr(sys, '_MEIPASS') + +def get_bundle_dir(): + """Get the PyInstaller bundle directory if the application is bundled.""" + if is_bundled(): + return sys._MEIPASS + return None diff --git a/tests/test_pyinstaller_compat.py b/tests/test_pyinstaller_compat.py new file mode 100644 index 000000000..41c6279fe --- /dev/null +++ b/tests/test_pyinstaller_compat.py @@ -0,0 +1,16 @@ +import unittest +from unittest.mock import patch +import sys + +from crewai.utilities.pyinstaller_compat import is_bundled, get_bundle_dir + + +class TestPyInstallerCompat(unittest.TestCase): + def test_is_bundled_normal(self): + self.assertFalse(is_bundled()) + + @patch.object(sys, 'frozen', True, create=True) + @patch.object(sys, '_MEIPASS', '/path/to/bundle', create=True) + def test_is_bundled_pyinstaller(self): + self.assertTrue(is_bundled()) + self.assertEqual(get_bundle_dir(), '/path/to/bundle')