-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathrun.py
More file actions
125 lines (105 loc) · 4.2 KB
/
run.py
File metadata and controls
125 lines (105 loc) · 4.2 KB
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
import uvicorn
import os
import sys
import importlib.util
def setup_package():
"""
Ensures the 'app' folder is treated as a Python package
by creating an __init__.py if it's missing.
"""
if os.path.exists("app") and not os.path.exists("app/__init__.py"):
print("⚙️ Creating missing app/__init__.py...")
with open("app/__init__.py", "w") as f:
f.write("")
def pre_check_imports():
"""
Diagnoses the project structure and finds the correct main file.
"""
# 1. Check Root
if getattr(sys, 'frozen', False):
# PyInstaller Mode: We assume the app is bundled correctly.
return "app.main:app"
if os.path.exists("main.py"):
print("[OK] Found main.py in root folder.")
return "main:app"
# 2. Check App Folder (Your case)
elif os.path.exists("app/main.py"):
print("[OK] Found main.py inside 'app' folder.")
# Ensure it's a valid package
setup_package()
return "app.main:app"
else:
print("\n[ERROR] CRITICAL: File 'main.py' not found!")
print(f"Searched in: {os.getcwd()}")
print("Please ensure 'main.py' is in this folder or inside 'app/'.\n")
return None
import tkinter
from tkinter import filedialog
if __name__ == "__main__":
# Support for running small scripts (like the folder picker) via subprocess
if len(sys.argv) > 1 and sys.argv[1] == '-c':
try:
source = sys.argv[2]
exec(source)
except Exception as e:
with open("picker_error.log", "w") as f:
f.write(f"Error executing script: {e}\n")
sys.exit()
# Ensure current directory is in Python path so imports work
sys.path.insert(0, os.getcwd())
# --- FIX FOR --noconsole MODE ---
class StreamLogger:
"""Fake file-like stream object that redirects writes to a file or nowhere."""
def __init__(self, filename=None):
self.filename = filename
def write(self, message):
if self.filename:
try:
with open(self.filename, "a") as f:
f.write(message)
except: pass
def flush(self):
pass
def isatty(self):
return False
# Redirect stdin/stdout/stderr if they are None (Windowless mode)
if sys.stdout is None:
sys.stdout = StreamLogger("app.log")
if sys.stderr is None:
sys.stderr = StreamLogger("error.log")
if sys.stdin is None:
sys.stdin = StreamLogger() # Dummy stdin
print("Starting YouTube Downloader Server...")
# 1. Find the app
app_string = pre_check_imports()
# 2. Create downloads folder if missing
if not os.path.exists("downloads"):
try:
os.makedirs("downloads")
except Exception as e:
print(f"Warning: Could not create downloads folder: {e}")
if app_string:
print("Open http://127.0.0.1:8000 in your browser")
try:
# Start Uvicorn
# Dynamically import the app object
module_name, app_name = app_string.split(":")
module = importlib.import_module(module_name)
app_obj = getattr(module, app_name)
# Auto-open browser
import webbrowser
from threading import Timer
def open_browser():
webbrowser.open("http://127.0.0.1:8000")
Timer(1.5, open_browser).start()
# IMPORTANT: log_config=None prevents Uvicorn from trying to configure logging with streams that might fail
uvicorn.run(app_obj, host="127.0.0.1", port=8000, log_config=None)
except KeyboardInterrupt:
print("\nServer stopped by user.")
except Exception as e:
# Log error since we can't print
with open("fatal_error.txt", "w") as f:
f.write(str(e))
else:
with open("fatal_error.txt", "w") as f:
f.write("Server could not start due to missing files.")