Raoul
Raoul

Reputation: 1892

Linux: cat to named pipe in a python script

I have a Java program that uses video from a framegrabber card. This program is launched through a python launcher.py.

The easiest way to read the video stream I found, is to make Java read on a named pipe, and this works perfectly. So my session is like:

$ mkfifo videopipe
$ cat /dev/video1>videopipe

and in a second terminal (since the cat command is blocking):

$ python launcher.py

I would like to automate this process. Unfortunately, the result is always the same: the Java application starts (confirmed through a print statement in the java program), but then the terminal stalls and nothing appears, exception or else.

Since this process works manually, I guess I am doing something wrong in the python program. To simplify things, I isolated the piping part:

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

which when run, outputs:

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

A little help would be very much appreciated :-)

Upvotes: 0

Views: 844

Answers (1)

Charles Duffy
Charles Duffy

Reputation: 295373

If you're using shell=True, just pass a string:

BASH_PIPE_VIDEO = 'cat /dev/video1 > videopipe'

Currently, cat is passed to the shell as your script, and /dev/video>videopipe is passed to that shell as a literal argument -- not parsed as part of the script text at all, and having no effect since the script (just calling cat) doesn't look at its arguments.


Alternately, to avoid needless shell use (and thus shell-related bugs such as shellshock, and potential for injection attacks if you were accepting any argument from a non-hardcoded source):

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

On a note unrelated to your "cat to named pipe" question -- be sure you get your spaces correct.

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

...uses the name <space>/dev/video1, with a leading space, as the input device; it's the same as running v4l2-ctl "-d /dev/video1" in shell, which would cause the same problem.

Be sure that you split your arguments correctly:

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

Upvotes: 2

Related Questions