Python模块运行,但函数不运行

Python模块运行,但函数不运行,python,raspberry-pi,network-programming,streaming,Python,Raspberry Pi,Network Programming,Streaming,虽然我了解Python语法,并编写了一些数据处理和分析脚本(光谱和图像),但我从未真正使用过网络或流媒体,我必须承认我的编程技能相当低。也许,我正试图处理比我目前的技能所允许的更多的事情,但这可能是发展的常见情况 不管怎样,我正在开发(另一个)gui客户端来控制Raspberry Pi摄像头——既为了好玩,也为了学习。长话短说,我想从这个gui运行一个流式http服务器。我选择了一种现成的解决方案,并遵循了这个食谱 然后它将不会流化,尽管输出和服务器对象已创建。我真的很困惑,谁能回答为什么如果

虽然我了解Python语法,并编写了一些数据处理和分析脚本(光谱和图像),但我从未真正使用过网络或流媒体,我必须承认我的编程技能相当低。也许,我正试图处理比我目前的技能所允许的更多的事情,但这可能是发展的常见情况

不管怎样,我正在开发(另一个)gui客户端来控制Raspberry Pi摄像头——既为了好玩,也为了学习。长话短说,我想从这个gui运行一个流式http服务器。我选择了一种现成的解决方案,并遵循了这个食谱

然后它将不会流化,尽管输出和服务器对象已创建。我真的很困惑,谁能回答为什么如果答案很简单,问题也很愚蠢,我不会感到惊讶。因此,如果有人能推荐一些教程或简单的阅读资料来编写用于流式传输/接收数据的服务器/客户端,我将不胜感激

另一件事是,我希望能够在请求时终止此服务器-为此,我想好的解决方案是使用线程模块,让gui和服务器在单独的线程中运行? 非常感谢


你是对的,第一个答案很简单

问题在于,当定义变量的代码位于名为
main
的函数中时,您试图在
StreamingHandler
中读取的变量
output
不在范围内。

因此,您需要找到一种方法将
输出
变量传递给服务器。我的方法是在
StreamingHandler
中将输出声明为类变量,并在实例化新的
StreamingServer
时添加
output
作为参数,如下所示:

导入io
进口皮卡梅拉
导入日志记录
导入socketserver
从线程导入条件
从http导入服务器
第“”页\
网页说明
"""
类StreamingOutput(对象):
定义初始化(自):
self.frame=None
self.buffer=io.BytesIO()
self.condition=条件()
def写入(自身,buf):
如果buf.startswith(b'\xff\xd8'):
#新建帧,复制现有缓冲区的内容并通知所有
#客户可以使用
self.buffer.truncate()
有了自己的条件:
self.frame=self.buffer.getvalue()
self.condition.notify_all()
self.buffer.seek(0)
返回self.buffer.write(buf)
类StreamingHandler(server.BaseHTTPRequestHandler):
输出=无
def do_获得(自我):
如果self.path=='/':
self.send_响应(301)
self.send_头('Location','/index.html'))
self.end_头()
elif self.path='/index.html':
内容=页面编码('utf-8')
自我发送_响应(200)
self.send_标题('Content-Type','text/html')
self.send_头('Content-Length',len(Content))
self.end_头()
self.wfile.write(内容)
elif self.path='/stream.mjpg':
自我发送_响应(200)
self.send_头('Age',0)
self.send_头('Cache-Control','no-Cache,private')
self.send_头('Pragma','no cache')
self.send_头('Content-Type','multipart/x-mixed-replace;boundary=FRAME')
self.end_头()
尝试:
尽管如此:
使用StreamingHandler.output.condition:
StreamingHandler.output.condition.wait()
frame=StreamingHandler.output.frame
self.wfile.write(b'--FRAME\r\n')
self.send_头('Content-Type','image/jpeg')
self.send_头('Content-Length',len(frame))
self.end_头()
self.wfile.write(帧)
self.wfile.write(b'\r\n')
例外情况除外,如e:
日志记录。警告(
'已删除流式处理客户端%s:%s',
self.client_地址,str(e))
其他:
self.send_错误(404)
self.end_头()
类StreamingServer(socketserver.ThreadingMixIn,server.HTTPServer):
允许重新使用地址=真
守护进程线程=True
定义初始化(self、地址、处理程序、输出):
handler.output=输出
super()。\uuuuu init\uuuuuuu(地址,处理程序)
def main():
使用picamera.picamera(分辨率为640x480',帧速率为24)作为相机:
输出=流化输出()
照相机.开始录制(输出,格式='mjpeg')
尝试:
地址=('',8000)
服务器=StreamingServer(地址、StreamingHandler、输出)
服务器。永远为您服务()
除了(键盘中断):
照相机。停止录制()
如果uuuu name uuuuuu='\uuuuuuu main\uuuuuuu':
main()

我现在把你关于杀死服务器的问题留给我的博学的同事。

嗨,谢谢你的提示。事实上,它是按照描述的那样工作的,解释也很清楚,尽管我仍然对类变量有点困惑。当然,如果你是面向对象编程的新手,这部分有点棘手。本文很好地介绍了类和对象中不同类型的变量:
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
description of webpage
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with output.condition:
                        output.condition.wait()
                        frame = output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True

with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
    output = StreamingOutput()
    camera.start_recording(output, format='mjpeg')
    try:
        address = ('', 8000)
        server = StreamingServer(address, StreamingHandler)
        server.serve_forever()
    finally:
        camera.stop_recording()
def main():
    with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
            output = StreamingOutput()
            camera.start_recording(output, format='mjpeg')
            try:
                address = ('', 8000)
                server = StreamingServer(address, StreamingHandler)
                server.serve_forever()
            except(KeyboardInterrupt):
                camera.stop_recording()

if __name__ == '__main__':
    main()
output = 5

def test():
    print(output)

# the following statement runs fine, output is in scope because it
# was defined in the top-level scope   
test()

def test_2():
    print(output_2)

def main():
    output_2 = 6
    test_2()

# error! test_2 doesn't know the value of output_2 because the
# output_2 variable was declared within main()
main()
import io
import picamera
import logging
import socketserver
from threading import Condition
from http import server

PAGE="""\
<html>
description of webpage
</html>
"""

class StreamingOutput(object):
    def __init__(self):
        self.frame = None
        self.buffer = io.BytesIO()
        self.condition = Condition()

    def write(self, buf):
        if buf.startswith(b'\xff\xd8'):
            # New frame, copy the existing buffer's content and notify all
            # clients it's available
            self.buffer.truncate()
            with self.condition:
                self.frame = self.buffer.getvalue()
                self.condition.notify_all()
            self.buffer.seek(0)
        return self.buffer.write(buf)

class StreamingHandler(server.BaseHTTPRequestHandler):
    output = None

    def do_GET(self):
        if self.path == '/':
            self.send_response(301)
            self.send_header('Location', '/index.html')
            self.end_headers()
        elif self.path == '/index.html':
            content = PAGE.encode('utf-8')
            self.send_response(200)
            self.send_header('Content-Type', 'text/html')
            self.send_header('Content-Length', len(content))
            self.end_headers()
            self.wfile.write(content)
        elif self.path == '/stream.mjpg':
            self.send_response(200)
            self.send_header('Age', 0)
            self.send_header('Cache-Control', 'no-cache, private')
            self.send_header('Pragma', 'no-cache')
            self.send_header('Content-Type', 'multipart/x-mixed-replace; boundary=FRAME')
            self.end_headers()
            try:
                while True:
                    with StreamingHandler.output.condition:
                        StreamingHandler.output.condition.wait()
                        frame = StreamingHandler.output.frame
                    self.wfile.write(b'--FRAME\r\n')
                    self.send_header('Content-Type', 'image/jpeg')
                    self.send_header('Content-Length', len(frame))
                    self.end_headers()
                    self.wfile.write(frame)
                    self.wfile.write(b'\r\n')
            except Exception as e:
                logging.warning(
                    'Removed streaming client %s: %s',
                    self.client_address, str(e))
        else:
            self.send_error(404)
            self.end_headers()

class StreamingServer(socketserver.ThreadingMixIn, server.HTTPServer):
    allow_reuse_address = True
    daemon_threads = True
    def __init__(self, address, handler, output):
        handler.output = output
        super().__init__(address, handler)

def main():
    with picamera.PiCamera(resolution='640x480', framerate=24) as camera:
            output = StreamingOutput()
            camera.start_recording(output, format='mjpeg')
            try:
                address = ('', 8000)
                server = StreamingServer(address, StreamingHandler, output)
                server.serve_forever()
            except(KeyboardInterrupt):
                camera.stop_recording()

if __name__ == '__main__':
    main()