Python aiohttp服务器提供“ConnectionResetError:无法写入关闭的传输”

2024-10-03 09:16:43 发布

您现在位置:Python中文网/ 问答频道 /正文

我黑了一个小mjpeg服务器,大部分是从互联网上找到的例子中复制的。在

它监视一个目录,如果该目录中的jpeg文件发生更改,则会将其通过流发送到浏览器。在

因此,要使用这个服务器,需要创建一个目录(在运行python程序的同一个目录中):

mkdir -p previews/{dirtowatch}

将上面一行中的“dirtowatch”替换为类似“test”的任意文本-请注意,您将在URL上放置与“dirtowatch”URL param相同的文本。在

当一个名为预览.jpeg被放入您创建的“test”目录中,将被流式传输到浏览器。在

把这个放到你的浏览器中:http://**address**:8080/?dirtowatch=testaddress替换为运行Python程序的地址。在

另外,将任何jpeg文件放入python程序目录并命名占位符.jpeg-如果dirtowatch中没有jpeg,则将发送此文件。在

总的想法是你可以替换预览.jpeg不管你想要什么样的jpeg图像,它都会流到浏览器上。在

它似乎工作得很好。在

除了不断出错,有人能告诉我我做错了什么吗?在

^{pr2}$

这是源代码。在

import asyncio
from aiohttp import web
from asyncio import CancelledError
from uuid import uuid4
from aiohttp.web import StreamResponse
import os
import glob
import os, time

with open('placeholder.jpeg', mode='rb') as file:  # b is important -> binary
    placeholder_img_bytes = file.read()

async def handle_async_mjpeg_stream(request):
    """
    if the user specifies a dirtowatch url param
    then this monitors a directory of that name
    it checks a single preview jpeg file
    if that jpeg file changes then it sends it to the client
    """
    dirtowatch = request.rel_url.query.get('dirtowatch', None)
    if not dirtowatch:
        return web.HTTPNotFound()
    print(request.rel_url.query['dirtowatch'])
    response = web.StreamResponse()

    response.content_type = ('multipart/x-mixed-replace; '
                             'boundary=--jpegboundary')
    await response.prepare(request)

    async def write(img_bytes):
        """Write image to stream."""
        await response.write(bytes(
            '--jpegboundary\r\n'
            'Content-Type: image/jpeg\r\n'
            'Content-Length: {}\r\n\r\n'.format(
                len(img_bytes)), 'utf-8') + img_bytes + b'\r\n')

    last_image = None
    last_file_sent_modified_date = None
    try:
        while True:
            filename = f'previews/{dirtowatch}/preview.jpeg'
            # note that we check file modification date at nanosecond resolution
            this_file_modified_date = None
            try:
                this_file_modified_date = os.stat(filename).st_mtime_ns
                if last_file_sent_modified_date == this_file_modified_date:
                    # the file has not changed on the disk, wait and try again
                    print('-', end='', flush=True)
                    await asyncio.sleep(0.2) # 200ms/5fps
                    continue
                print('+', end='', flush=True)
                with open(filename, mode='rb') as file:  # b is important -> binary
                    img_bytes = file.read()
            except:
                img_bytes = placeholder_img_bytes
            if not img_bytes:
                # sometimes the file read will fail to read data
                # perhaps because a new file is bring copied in
                # we just ignore that by continuing
                continue
            if img_bytes is not None and img_bytes != last_image:
                await write(img_bytes)
                # Chrome seems to always ignore first picture,
                # print it twice.
                if last_image is None:
                    await write(img_bytes)
                last_image = img_bytes
                await response.drain()
            last_file_sent_modified_date = this_file_modified_date
    finally:
        await response.write_eof()

async def main():
    server = web.Server(handle_async_mjpeg_stream)
    runner = web.ServerRunner(server)
    await runner.setup()
    listen_address = '0.0.0.0'
    port = '8080'
    site = web.TCPSite(runner, listen_address, port)
    await site.start()
    print(f"======= MJPEG server on http://{listen_address}:8080/ ======")

    # pause here for very long time by serving HTTP requests and
    # waiting for keyboard interruption
    await asyncio.sleep(100*3600)

loop = asyncio.get_event_loop()

try:
    loop.run_until_complete(main())
except KeyboardInterrupt:
    pass
loop.close()


Tags: import目录nonewebimgdateifbytes