Python模块运行,但函数不运行
虽然我了解Python语法,并编写了一些数据处理和分析脚本(光谱和图像),但我从未真正使用过网络或流媒体,我必须承认我的编程技能相当低。也许,我正试图处理比我目前的技能所允许的更多的事情,但这可能是发展的常见情况 不管怎样,我正在开发(另一个)gui客户端来控制Raspberry Pi摄像头——既为了好玩,也为了学习。长话短说,我想从这个gui运行一个流式http服务器。我选择了一种现成的解决方案,并遵循了这个食谱 然后它将不会流化,尽管输出和服务器对象已创建。我真的很困惑,谁能回答为什么如果答案很简单,问题也很愚蠢,我不会感到惊讶。因此,如果有人能推荐一些教程或简单的阅读资料来编写用于流式传输/接收数据的服务器/客户端,我将不胜感激 另一件事是,我希望能够在请求时终止此服务器-为此,我想好的解决方案是使用线程模块,让gui和服务器在单独的线程中运行? 非常感谢Python模块运行,但函数不运行,python,raspberry-pi,network-programming,streaming,Python,Raspberry Pi,Network Programming,Streaming,虽然我了解Python语法,并编写了一些数据处理和分析脚本(光谱和图像),但我从未真正使用过网络或流媒体,我必须承认我的编程技能相当低。也许,我正试图处理比我目前的技能所允许的更多的事情,但这可能是发展的常见情况 不管怎样,我正在开发(另一个)gui客户端来控制Raspberry Pi摄像头——既为了好玩,也为了学习。长话短说,我想从这个gui运行一个流式http服务器。我选择了一种现成的解决方案,并遵循了这个食谱 然后它将不会流化,尽管输出和服务器对象已创建。我真的很困惑,谁能回答为什么如果
你是对的,第一个答案很简单 问题在于,当定义变量的代码位于名为
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()