Ethscriptions commited on
Commit
e8bd76b
·
verified ·
1 Parent(s): 1c8f582

Update app.py

Browse files
Files changed (1) hide show
  1. app.py +62 -27
app.py CHANGED
@@ -4,10 +4,23 @@ import os
4
  import threading
5
  import time
6
  import logging
 
7
 
8
  # 配置日志
9
  logging.basicConfig(level=logging.INFO)
10
 
 
 
 
 
 
 
 
 
 
 
 
 
11
  class TorrentSession:
12
  def __init__(self):
13
  self.ses = lt.session()
@@ -40,34 +53,49 @@ class DownloadState:
40
  self.status = "等待开始"
41
  self.info_hash = ""
42
 
43
- def init_session_state():
44
- if 'download' not in st.session_state:
45
- state = DownloadState()
46
- st.session_state.download = {
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
47
  'progress': state.progress,
48
  'is_downloading': state.is_downloading,
49
  'complete': state.complete,
50
  'file_path': state.file_path,
51
  'status': state.status,
52
  'info_hash': state.info_hash
53
- }
54
 
55
- def sync_session_state():
56
- state = DownloadState()
57
- st.session_state.download.update({
58
- 'progress': state.progress,
59
- 'is_downloading': state.is_downloading,
60
- 'complete': state.complete,
61
- 'file_path': state.file_path,
62
- 'status': state.status,
63
- 'info_hash': state.info_hash
64
- })
65
 
66
  def download_worker(magnet_link, save_path):
67
  try:
68
  state = DownloadState()
69
  ts = TorrentSession()
70
 
 
 
 
 
 
71
  # 使用新版API添加磁力链接
72
  params = {
73
  'save_path': save_path,
@@ -77,12 +105,14 @@ def download_worker(magnet_link, save_path):
77
 
78
  handle = lt.add_magnet_uri(ts.ses, magnet_link, params)
79
  state.info_hash = str(handle.info_hash())
 
80
 
81
  # 事件驱动等待元数据
82
  state.status = "等待元数据..."
83
- logging.info("等待元数据...")
84
 
85
  metadata_received = False
 
86
  while not metadata_received:
87
  ts.process_alerts()
88
  for alert in ts.alerts:
@@ -90,12 +120,14 @@ def download_worker(magnet_link, save_path):
90
  if alert.handle == handle:
91
  metadata_received = True
92
  break
 
 
93
  time.sleep(0.5)
94
 
95
  # 获取文件信息
96
  ti = handle.get_torrent_info()
97
  state.status = f"开始下载 {ti.name()}"
98
- logging.info(f"开始下载: {ti.name()}")
99
 
100
  # 启动下载
101
  handle.set_sequential_download(True)
@@ -103,11 +135,13 @@ def download_worker(magnet_link, save_path):
103
 
104
  # 下载进度监控
105
  state.is_downloading = True
 
 
106
  while not handle.status().is_seeding:
107
  status = handle.status()
108
  state.progress = status.progress * 100
109
 
110
- # 检查种子状态
111
  if status.state == lt.torrent_status.downloading_metadata:
112
  state.status = "获取元数据..."
113
  elif status.state == lt.torrent_status.downloading:
@@ -116,6 +150,7 @@ def download_worker(magnet_link, save_path):
116
  peers = status.num_peers
117
  state.status = f"下载中: {dl:.1f}kB/s ↑{up:.1f}kB/s ↔{peers} peers"
118
 
 
119
  time.sleep(1)
120
 
121
  # 下载完成
@@ -123,17 +158,17 @@ def download_worker(magnet_link, save_path):
123
  state.complete = True
124
  state.file_path = save_path
125
  state.status = "下载完成"
126
- logging.info("下载完成")
127
 
128
  except Exception as e:
129
  logging.error(f"下载错误: {str(e)}")
130
  state.status = f"错误: {str(e)}"
131
  state.is_downloading = False
 
132
  finally:
133
- sync_session_state()
134
 
135
  # Streamlit界面
136
- init_session_state()
137
  st.title("🚀 磁力链接下载器")
138
 
139
  with st.form("magnet_form"):
@@ -148,9 +183,9 @@ with st.form("magnet_form"):
148
  save_dir = "./downloads"
149
  os.makedirs(save_dir, exist_ok=True)
150
 
151
- state = DownloadState()
152
- state.reset()
153
- sync_session_state()
154
 
155
  threading.Thread(
156
  target=download_worker,
@@ -158,8 +193,8 @@ with st.form("magnet_form"):
158
  daemon=True
159
  ).start()
160
 
161
- # 状态显示
162
- sync_session_state()
163
 
164
  if st.session_state.download['is_downloading']:
165
  cols = st.columns([1,3])
@@ -189,7 +224,7 @@ if st.session_state.download['complete']:
189
  if 'monitor' not in st.session_state:
190
  def status_monitor():
191
  while True:
192
- sync_session_state()
193
  time.sleep(0.5)
194
 
195
  threading.Thread(target=status_monitor, daemon=True).start()
 
4
  import threading
5
  import time
6
  import logging
7
+ from contextlib import contextmanager
8
 
9
  # 配置日志
10
  logging.basicConfig(level=logging.INFO)
11
 
12
+ # 初始化锁
13
+ session_lock = threading.Lock()
14
+
15
+ @contextmanager
16
+ def session_guard():
17
+ """线程安全的session_state访问上下文管理器"""
18
+ with session_lock:
19
+ try:
20
+ yield
21
+ finally:
22
+ pass
23
+
24
  class TorrentSession:
25
  def __init__(self):
26
  self.ses = lt.session()
 
53
  self.status = "等待开始"
54
  self.info_hash = ""
55
 
56
+ # 关键改进点:强化初始化机制
57
+ def safe_init_session():
58
+ """线程安全的session_state初始化"""
59
+ with session_guard():
60
+ if 'download' not in st.session_state:
61
+ state = DownloadState()
62
+ st.session_state.download = {
63
+ 'progress': state.progress,
64
+ 'is_downloading': state.is_downloading,
65
+ 'complete': state.complete,
66
+ 'file_path': state.file_path,
67
+ 'status': state.status,
68
+ 'info_hash': state.info_hash
69
+ }
70
+ logging.info("Session state initialized")
71
+
72
+ def safe_sync_session():
73
+ """双重保障的状态同步机制"""
74
+ safe_init_session() # 同步前确保初始化
75
+ state = DownloadState()
76
+ with session_guard():
77
+ st.session_state.download.update({
78
  'progress': state.progress,
79
  'is_downloading': state.is_downloading,
80
  'complete': state.complete,
81
  'file_path': state.file_path,
82
  'status': state.status,
83
  'info_hash': state.info_hash
84
+ })
85
 
86
+ # 初始化session状态(主线程保障)
87
+ safe_init_session()
 
 
 
 
 
 
 
 
88
 
89
  def download_worker(magnet_link, save_path):
90
  try:
91
  state = DownloadState()
92
  ts = TorrentSession()
93
 
94
+ # 重置状态
95
+ with session_guard():
96
+ state.reset()
97
+ safe_sync_session()
98
+
99
  # 使用新版API添加磁力链接
100
  params = {
101
  'save_path': save_path,
 
105
 
106
  handle = lt.add_magnet_uri(ts.ses, magnet_link, params)
107
  state.info_hash = str(handle.info_hash())
108
+ safe_sync_session()
109
 
110
  # 事件驱动等待元数据
111
  state.status = "等待元数据..."
112
+ safe_sync_session()
113
 
114
  metadata_received = False
115
+ start_time = time.time()
116
  while not metadata_received:
117
  ts.process_alerts()
118
  for alert in ts.alerts:
 
120
  if alert.handle == handle:
121
  metadata_received = True
122
  break
123
+ if time.time() - start_time > 300: # 5分钟超时
124
+ raise TimeoutError("获取元数据超时")
125
  time.sleep(0.5)
126
 
127
  # 获取文件信息
128
  ti = handle.get_torrent_info()
129
  state.status = f"开始下载 {ti.name()}"
130
+ safe_sync_session()
131
 
132
  # 启动下载
133
  handle.set_sequential_download(True)
 
135
 
136
  # 下载进度监控
137
  state.is_downloading = True
138
+ safe_sync_session()
139
+
140
  while not handle.status().is_seeding:
141
  status = handle.status()
142
  state.progress = status.progress * 100
143
 
144
+ # 状态更新
145
  if status.state == lt.torrent_status.downloading_metadata:
146
  state.status = "获取元数据..."
147
  elif status.state == lt.torrent_status.downloading:
 
150
  peers = status.num_peers
151
  state.status = f"下载中: {dl:.1f}kB/s ↑{up:.1f}kB/s ↔{peers} peers"
152
 
153
+ safe_sync_session()
154
  time.sleep(1)
155
 
156
  # 下载完成
 
158
  state.complete = True
159
  state.file_path = save_path
160
  state.status = "下载完成"
161
+ safe_sync_session()
162
 
163
  except Exception as e:
164
  logging.error(f"下载错误: {str(e)}")
165
  state.status = f"错误: {str(e)}"
166
  state.is_downloading = False
167
+ safe_sync_session()
168
  finally:
169
+ safe_sync_session()
170
 
171
  # Streamlit界面
 
172
  st.title("🚀 磁力链接下载器")
173
 
174
  with st.form("magnet_form"):
 
183
  save_dir = "./downloads"
184
  os.makedirs(save_dir, exist_ok=True)
185
 
186
+ # 启动前同步状态
187
+ DownloadState().reset()
188
+ safe_sync_session()
189
 
190
  threading.Thread(
191
  target=download_worker,
 
193
  daemon=True
194
  ).start()
195
 
196
+ # 实时状态显示
197
+ safe_sync_session()
198
 
199
  if st.session_state.download['is_downloading']:
200
  cols = st.columns([1,3])
 
224
  if 'monitor' not in st.session_state:
225
  def status_monitor():
226
  while True:
227
+ safe_sync_session()
228
  time.sleep(0.5)
229
 
230
  threading.Thread(target=status_monitor, daemon=True).start()