Python模块运行,但功能不会

时间:2018-05-15 15:30:18

标签: python raspberry-pi network-programming streaming

虽然我知道Python的语法,并编写了一些用于数据处理和分析(光谱和图像)的脚本来完成这项工作,但我从未真正使用过网络或流媒体,我猜我必须承认我的编程技巧非常低。也许,我试图处理的不仅仅是我目前的技能允许,但这可能是发展的常见情况。

无论如何,我正在(另一个)gui-client工作来控制Raspberry Pi相机 - 无论是为了娱乐还是为了学习。简而言之,我想从这个gui运行一个流式http服务器。我找了一个现成的解决方案并按照这个方法

http://picamera.readthedocs.io/en/latest/recipes2.html#web-streaming

lazy var myTableView: UITableView = {
    let tableView = UITableView()

    tableView.translatesAutoresizingMaskIntoConstraints = false
    tableView.backgroundColor = .brown

    tableView.delegate = self
    tableView.dataSource = self

    return tableView
}()

好的,如果它作为独立的应用程序运行,那么这段代码可以正常工作。但是,如果我试着让它作为一个函数运行,即如果我想在类构造之后做这样的smth

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()

然后它将不会流式传输,尽管创建了输出和服务器对象。我真的很困惑,有谁可以,请回答为什么? - 如果答案变得简单并且问题很愚蠢,我不会感到惊讶,因此如果有人可以在编写服务器/客户端来流式传输/接收数据时推荐一些教程或简单阅读,将不胜感激。

另一件事是我希望能够根据请求杀死这个服务器 - 为此,我想好的解决方案是使用线程模块并让gui和服务器在不同的线程中运行? 非常感谢

<磷>氮

1 个答案:

答案 0 :(得分:0)

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

问题在于,当您定义它的代码位于名为{{1的函数内部时,您尝试在output中读取的变量StreamingHandler不在范围中}}。

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() 变量传递给服务器。我的方法是在output中将输出声明为类变量,并在实例化新的StreamingHandler时添加output作为参数,如下所示:

StreamingServer

我现在就把关于杀死服务器的问题留给我的学员们。