我有一个在用于分割音频文件的服务器上运行的代码。我使用 websockets 来触发浏览器的这个过程。
问题是,这个分割过程的每个触发器都会创建 10 个新的 python 进程,这些进程不会被杀死,从而在运行一段时间后导致内存错误。 我不明白为什么创建这些进程以及如何改进脚本。 现在我正在使用一种黑客方法,每天运行一次 cron 作业,杀死任何剩余的进程。 任何有关这些进程的作用或创建它们的原因以及如何在脚本运行后自动终止它们的指示都会很棒。
代码:
#!/usr/bin/env python
import websockets
#import aiohttp
import asyncio
from pathlib import Path
from io import BytesIO
from spleeter.separator import Separator
import sys
import tempfile
import os
from zipfile import ZipFile
async def split(websocket, path):
print("split started")
stems = await websocket.recv()
audioFormat = await websocket.recv()
bitRate = await websocket.recv()
audio_bytes = await websocket.recv()
separator = Separator('spleeter:'+stems+'stems')
temp, pathname = tempfile.mkstemp()
file_paths = []
p = Path('/tmp/filename/'+str(pathname).split('/')[2])
if not (os.path.exists(p)):
print('New Path')
with open(pathname, mode='wb') as f:
f.write(audio_bytes)
print('Writing to file ' + str(f) + 'with seperator: ' + str(separator))
if audioFormat == "mp3":
print("mp3")
separator.separate_to_file(pathname, "/tmp/filename", codec="mp3", bitrate=bitRate)
else:
print("wav")
separator.separate_to_file(pathname, "/tmp/filename")
separator.join()
print('Separating finished')
oldwd = os.getcwd()
os.chdir(p)
for entry in os.scandir(path='.'):
print('Appending file: ' + str(entry))
if entry.is_file():
file_paths.append(entry)
with ZipFile(p / 'files.zip','w') as zip:
for f in file_paths:
zip.write(f)
print('Zip created')
os.chdir(oldwd)
f=open(p / 'files.zip', "rb")
contents = f.read()
await websocket.send(contents)
print('Zip sent to client')
async def main():
print("main called")
async with websockets.serve(
split,
# "0.0.0.0",
"localhost",
9014,
max_size = None,
create_protocol=websockets.basic_auth_protocol_factory(
realm="my dev server",
credentials=("TEST", "CREDS"),
)
):
await asyncio.Future() # run forever
asyncio.run(main())
最佳答案
我遇到了类似的内存泄漏问题,问题是客户端永远不会关闭连接,因此每次客户端连接时,都会打开一个新的 websocket 并永远卡在内存中,等待接收更多消息。
就我而言,我知道套接字连接的生命周期应该不到一分钟,并且可以安全地假设一分钟后同一套接字连接内不会再收到任何消息,所以我设置了 60 秒的超时。
请注意,当您设置超时时,它会引发超时异常,因此您需要处理该异常。
所以代替:
data = wait websocket.recv()
我用过:
data = wait asyncio.wait_for(websocket.recv(), timeout=60)
super 简化的代码来说明:
import asyncio
import websockets
async def handler(websocket):
try:
# Added a timeout so it wouldn't wait indefinitely
await asyncio.wait_for(websocket.recv(), timeout=60)
# do some work...
except websockets.exceptions.ConnectionClosed:
print("Client disconnected")
finally:
# Unregister.
print("Unregistering websocket")
关于Python Websocket 模块继续启动未被杀死的进程,导致内存问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/69801985/