首页 > 解决方案 > 无法将子进程对象存储在变量中并使用 stdin.write() 写入它

问题描述

我正在为 Raspberry Pi 开发一个项目,其中服务器接收 POST 请求并使用给定的 URL 启动 OMXplayer 进程来播放视频。到目前为止,它能够开始播放视频就好了。但是,我希望能够与该omxplayer过程进行交互,以便我可以播放/暂停视频,以及向前和向后跳转。我也希望能够终止该进程。这应该可以通过调用进程'stdin.write()和来实现terminate(),但是当我尝试执行这些方法(通过触发适当的GET路径)时,我不断收到错误 NoneType object has no attribute ...,表明变量 video_process 没有在 play_video() 中分配,即使函数被执行。

我已经尝试了很多方法来尝试让它工作,比如 makignvideo_process的一个属性,ConfigurationServer但它们都产生相同的错误,我觉得我错过了一些非常明显的东西。我尝试改编其他 SO 帖子中的示例代码:

from subprocess import Popen, PIPE
p = Popen(['omxplayer', filePath], stdin=PIPE, stdout=PIPE, stderr=PIPE, close_fds=True)
p.stdin.write(' ') # sends a space to the running process
p.stdin.flush() # if the above isn't enough, try adding a flush

但什么都行不通。主要代码如下。

video_process = None

def play_video(url, orientation=0):
    global video_process
    p = subprocess.Popen(["omxplayer -o both --orientation {} --blank `youtube-dl -g -f best \"{}\"` &".format(orientation, url)], shell=True, stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE, close_fds=True)
    video_process = p

def toggle_play_video():
    video_process.stdin.write(' ')
    video_process.stdin.flush()

def stop_video():
    video_process.terminate()
    video_process = None
        

class ConfigurationServer(http.server.BaseHTTPRequestHandler):
    
    # when starting a video, the process is stored here so that commands (pause, play, arrows) can be sent to it when other requests are received.

    def do_GET(self):
        if self.path == '/togglePlayVideo':
            self.send_response(200)
            try:
                toggle_play_video()
            except Exception as e:
                print(e)
            return

        elif self.path == '/jumpForwardsVideo':
            self.send_response(200)
            try:
                self.video_process.stdin.write('^[[C')
                self.video_process.stdin.flush()
            except Exception as e:
                print(e)
            return

        elif self.path == '/jumpBackwardsVideo':
            self.send_response(200)
            try:
                self.video_process.stdin.write('^[[D')
                self.video_process.stdin.flush()
            except Exception as e:
                print(e)
            return

        elif self.path == '/killVideo':
            self.send_response(200)
            try:
                stop_video()
            except Exception as e:
                print(e)
            return

        else:
            self.send_response(404)
            data_to_send = ""

        try:
            with open(filePath, 'r') as file:
                self.wfile.write(bytes(file.read(), 'utf-8'))
        except:
            self.wfile.write(bytes('', 'utf-8'))

        return

    def do_POST(self):
        
        if self.path.endswith("/playVideo"):
            content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
            youtube_link = self.rfile.read(content_length).decode('utf-8')

            self.send_response(200)

            play_video(youtube_link)
            

        content_length = int(self.headers['Content-Length']) # <--- Gets the size of data
        post_data = self.rfile.read(content_length) # <--- Gets the data itself
        print("POST request,\nPath: {}\nHeaders:\n{}\n\nBody:\n{}\n".format(str(self.path), str(self.headers), post_data.decode('utf-8')))

        self.send_response(200)
        self.wfile.write("POST request for {}".format(self.path).encode('utf-8'))

谢谢,我将不胜感激任何帮助,因为我已经做到了最后一根稻草。

标签: python-3.xprocesspopenomxplayer

解决方案


推荐阅读