File size: 5,459 Bytes
18dd400 |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 |
# 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
|