| # Entry Point Conflict Resolution | |
| ## Problem Resolved | |
| **Issue**: Both `app.py` and `main.py` were attempting to launch Gradio on port 7860, causing port conflicts. | |
| **Root Cause**: | |
| - `app.py` has a `if __name__ == "__main__":` block that launches Gradio | |
| - `main.py` was also trying to create and launch its own Gradio instance | |
| - Both tried to bind to port 7860 simultaneously | |
| ## Solution Implemented | |
| ### Single Entry Point Architecture | |
| **For Hugging Face Spaces Deployment:** | |
| - `main.py` is the **only entry point** (configured in `README.md` as `app_file: main.py`) | |
| - `main.py` imports the interface from `app.py` without triggering its launch | |
| - `main.py` handles the launch configuration | |
| **For Local Development/Testing:** | |
| - `app.py` can still be run directly (`python app.py`) | |
| - When run directly, `app.py` launches with its own configuration | |
| - This allows developers to test the app independently | |
| ## How It Works | |
| ### Import Behavior in Python | |
| When `main.py` imports from `app.py`: | |
| ```python | |
| from app import create_mobile_optimized_interface | |
| ``` | |
| - β All top-level code in `app.py` executes (orchestrator initialization, etc.) | |
| - β The function `create_mobile_optimized_interface()` becomes available | |
| - β The `if __name__ == "__main__":` block does **NOT** execute (because `__name__` != `"__main__"` when imported) | |
| ### Current Structure | |
| ``` | |
| app.py: | |
| - Defines: create_mobile_optimized_interface() β Returns (demo, components) | |
| - Has: if __name__ == "__main__": launch code β Only runs when app.py executed directly | |
| main.py: | |
| - Imports: create_mobile_optimized_interface() from app.py | |
| - Calls: demo, components = create_mobile_optimized_interface() | |
| - Launches: demo.launch() with HF Spaces configuration | |
| ``` | |
| ## File Roles | |
| ### `app.py` | |
| - **Purpose**: Core application interface and logic | |
| - **When imported**: Provides interface creation function | |
| - **When executed directly**: Launches app for local testing | |
| - **Launch configuration**: Local-optimized (with share link for external access when not on HF Spaces) | |
| ### `main.py` | |
| - **Purpose**: HF Spaces entry point | |
| - **When executed**: Imports from app.py and launches | |
| - **Launch configuration**: HF Spaces-optimized (detects environment, adjusts share setting) | |
| - **HF Spaces requirement**: Must be specified as `app_file: main.py` in README.md | |
| ## Configuration | |
| ### Hugging Face Spaces Setup | |
| In `README.md`: | |
| ```yaml | |
| sdk: gradio | |
| app_file: main.py # β This tells HF Spaces to use main.py | |
| ``` | |
| ### Environment Detection | |
| Both files automatically detect if running on HF Spaces: | |
| ```python | |
| try: | |
| from spaces import GPU | |
| is_hf_spaces = True | |
| except ImportError: | |
| is_hf_spaces = False | |
| ``` | |
| **On HF Spaces:** | |
| - `share=False` (HF Spaces provides its own URL) | |
| - No warnings about share being unsupported | |
| **Locally:** | |
| - `share=True` (creates Gradio public link for external access) | |
| ## Benefits | |
| 1. β **No Port Conflicts**: Only one Gradio instance launches | |
| 2. β **Clean Separation**: Interface logic (app.py) vs. Launch logic (main.py) | |
| 3. β **Flexible Testing**: Can test app.py independently | |
| 4. β **HF Spaces Compatible**: Follows HF Spaces deployment patterns | |
| 5. β **Environment Aware**: Automatically adjusts configuration based on deployment environment | |
| ## Verification | |
| ### Check That Only One Instance Launches | |
| When running on HF Spaces: | |
| ```bash | |
| # Should see only one launch message: | |
| "β Application ready for launch" | |
| ``` | |
| ### Check Port Binding | |
| ```bash | |
| # Should only see one process on port 7860 | |
| netstat -ano | findstr :7860 # Windows | |
| lsof -i :7860 # Linux/Mac | |
| ``` | |
| ### Check Logs | |
| **When main.py is entry point (HF Spaces):** | |
| ``` | |
| π Starting AI Research Assistant MVP | |
| Creating interface from app.py (all handlers already initialized)... | |
| β Interface created with all API endpoints and handlers | |
| β Detected Hugging Face Spaces - using built-in public URL | |
| β Application ready for launch | |
| ``` | |
| **When app.py is executed directly (local):** | |
| ``` | |
| STARTING APP (direct execution) | |
| β Interface created | |
| LAUNCHING GRADIO APP | |
| Creating public Gradio share link for external access... (if not on HF Spaces) | |
| ``` | |
| ## Troubleshooting | |
| ### Issue: Port Still in Use | |
| **Check:** | |
| 1. Only one entry point is being executed | |
| 2. No other Python processes using port 7860 | |
| 3. Previous Gradio instance was properly terminated | |
| **Solution:** | |
| ```bash | |
| # Kill any existing Python processes | |
| taskkill /IM python.exe /F # Windows | |
| pkill -f python # Linux/Mac | |
| ``` | |
| ### Issue: app.py Launching When Imported | |
| **Check:** Verify `if __name__ == "__main__":` block is present and correctly indented | |
| **Solution:** This should never happen - Python's import mechanism prevents it. If it does, check for syntax errors or circular imports. | |
| ### Issue: API Endpoints Not Available | |
| **Check:** | |
| 1. `show_api=True` is set in launch configuration | |
| 2. API endpoints are registered in app.py (before import) | |
| 3. Both files use the same demo instance | |
| **Solution:** The demo instance is created in app.py and used by main.py, so endpoints should be available. Verify logs show "β API endpoint registered" messages. | |
| ## Summary | |
| β **Conflict resolved**: Single entry point architecture | |
| β **Port conflict eliminated**: Only main.py launches Gradio | |
| β **Environment aware**: Automatically detects HF Spaces vs. local | |
| β **Flexible**: Can still run app.py directly for testing | |
| β **Production ready**: Follows HF Spaces deployment best practices | |