【问题标题】:Linux: cat to named pipe in a python scriptLinux:cat 到 python 脚本中的命名管道
【发布时间】:2015-11-13 02:13:23
【问题描述】:

我有一个使用图像采集卡中的视频的 Java 程序。这个程序是通过pythonlauncher.py启动的。

我找到的读取视频流的最简单方法是让 Java 在命名管道上读取,这非常有效。所以我的会话是这样的:

$ mkfifo videopipe
$ cat /dev/video1>videopipe

在第二个终端中(因为cat 命令被阻塞):

$ python launcher.py

我想自动化这个过程。不幸的是,结果总是一样的:Java 应用程序启动(通过 java 程序中的 print 语句确认),但随后终端停止并且什么都没有出现,异常或其他。

由于这个过程是手动进行的,我想我在 python 程序中做错了什么。为了简单起见,我隔离了管道部分:

from subprocess import call, Popen, PIPE, check_call

BASH_SWITCHTO_WINTV = ['v4l2-ctl', '-d /dev/video1', '-i 2', '--set-standard=4']
BASH_CREATE_FIFO_PIPE = ['mkfifo', 'videopipe']
BASH_PIPE_VIDEO = 'cat /dev/video1>videopipe'

def run():
    try:
        print('running bash commands...')
        call(BASH_SWITCHTO_WINTV)
        call(BASH_CREATE_FIFO_PIPE)
        Popen(['cat', '/dev/video1'], stdout=open('videopipe', 'w'))
    except:
        raise RuntimeError('An error occured while piping the video')

if __name__ == '__main__':
    run()

运行时输出:

running bash commands...     
Failed to open  /dev/video1: No such file or directory

非常感谢您的帮助:-)

【问题讨论】:

  • '-d /dev/video1' 几乎可以肯定是一个错误。 '-d', '/dev/video1' 应该是两个单独的参数。 -i 2 也一样。您可以使用不带空格的'-d/dev/video1'-i2,具体取决于使用的解析器。
  • 也就是说:您当前的错误不是来自cat,而是来自v4l2-ctl
  • ...因为您告诉它打开一个名为 <space>/dev/video1 的文件,而不是 /dev/video1
  • 这在您的错误消息中也很明显,当修复以显示格式时 - 看看它在 /dev 之前有两个空格,而不是一个?
  • 如果你给你的java程序/dev/video1而不是videopipe会发生什么?在这种情况下,我看不出使用命名管道能给你带来什么。

标签: python linux pipe subprocess cat


【解决方案1】:

如果你使用shell=True,只需传递一个字符串:

BASH_PIPE_VIDEO = 'cat /dev/video1 > videopipe'

目前,cat 作为您的脚本传递给 shell,/dev/video>videopipe 作为文字参数传递给该 shell——根本不作为脚本文本的一部分进行解析,并且在脚本之后没有任何效果(只是调用cat)不看它的论点。


或者,为了避免不必要的 shell 使用(以及与 shell 相关的错误,如 shellshock,以及如果您接受来自非硬编码源的任何参数,则可能会发生注入攻击):

Popen(['cat', '/dev/video1'], stdout=open('videopipe, 'w'))

在与您的“cat to named pipe”问题无关的注释上——请确保您的空格正确。

BASH_SWITCHTO_WINTV = ['v4l2-ctl', '-d /dev/video1', ...]

...使用名称<space>/dev/video1前导空格,作为输入设备;和在shell中运行v4l2-ctl "-d /dev/video1"一样,会导致同样的问题。

确保正确拆分参数:

BASH_SWITCHTO_WINTV = ['v4l2-ctl', '-d', '/dev/video1', ...]

【讨论】:

  • 在尝试了各种其他清洁剂subprocess 方法后,我使用shell=True 登陆。我会纠正的。正如您将在编辑中看到的那样,我还更准确地隔离了问题(我认为)。
  • @Raoul,新的“孤立”问题几乎可以肯定与问题所涉及的cat 进程无关。请参阅问题本身的 cmets。
  • 太棒了,它有效。唯一剩下的是cat 命令仍然阻塞,所以我需要用另一个程序打开管道,然后才能继续启动我的java程序。有什么办法让它不阻塞?
  • 是的,你可以让它成为非阻塞的,但我不明白你为什么认为你需要这样做。
  • 您的 Java 程序从管道中读取数据,对吗?这将允许cat 继续进行。
猜你喜欢
  • 1970-01-01
  • 2021-10-10
  • 2011-10-13
  • 2021-05-19
  • 1970-01-01
  • 1970-01-01
  • 2018-07-10
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多