Python Forum
Echo call to VLC bash using subprocess.Popen on Linux - Printable Version

+- Python Forum (https://python-forum.io)
+-- Forum: Python Coding (https://python-forum.io/forum-7.html)
+--- Forum: General Coding Help (https://python-forum.io/forum-8.html)
+--- Thread: Echo call to VLC bash using subprocess.Popen on Linux (/thread-15088.html)

Pages: 1 2


Echo call to VLC bash using subprocess.Popen on Linux - LuukS001 - Jan-03-2019

I am using this both on my macosx and linux and it works well.
On linux the shell commands are slightly different:

vlc -I oldrc --rc-unix=/home/user/Documents/Sockets/socket1.sock
vlc -I oldrc --rc-unix=/home/user/Documents/Sockets/socket2.sock

and

echo play | nc -U /home/user/Documents/Sockets/socket1.sock
echo enqueue /home/user/Documents/DualscreenVLC/videos/MVI_2534.MP4 | nc -U /home/user/Documents/Sockets/socket1.sock

I am attempting to use subprocess.Popen in Python for further control but here I run into difficulties on Linux (Ubuntu). It either hangs on the stdout.read() call or when I take this away, all the shell commands are only executed after the script finishes and I get a broken pipe error. The issue seems to be specifically with the 'echo' commands. Did I migrate wrong?
This is the python script:

import subprocess
import time

Socket1Location = "/Users/user/socket1.sock"
Socket2Location = "/Users/user/socket2.sock"
video1 = "/Users/user/Documents/Scripts/DualscreenVLC/videos/video01.mp4"
video2 = "/Users/user/Documents/Scripts/DualscreenVLC/videos/video02.mp4"

def RunVLCCommand1(cmd):
    p = subprocess.Popen("echo " + cmd + " | nc -U " + Socket1Location, shell = True, stdout = subprocess.PIPE)
    errcode = p.wait()
    retval = p.stdout.read()
    print "returning: " + retval
    return retval
    
def RunVLCCommand2(cmd):
    p = subprocess.Popen("echo " + cmd + " | nc -U " + Socket2Location, shell = True, stdout = subprocess.PIPE)
    errcode = p.wait()
    retval = p.stdout.read()
    print "returning: " + retval
    return retval

subprocess.Popen(["/Applications/VLC.app/Contents/MacOS/VLC","--rc-unix=/Users/user/socket1.sock"])
subprocess.Popen(["/Applications/VLC.app/Contents/MacOS/VLC","--rc-unix=/Users/user/socket2.sock"])

#RunVLCCommand1 and 2 can now be used to send commands to VLC, for example RunVLCCommand1('play')



RE: Echo call to VLC bash using subprocess.Popen on Linux - Gribouillis - Jan-03-2019

Hi, try this perhaps
p = subprocess.run("echo " + cmd + " | nc -U " + Socket1Location, shell = True, capture_output=True)
print(p.returncode)
print(p.stdout)



RE: Echo call to VLC bash using subprocess.Popen on Linux - LuukS001 - Jan-03-2019

Thank you, I tried it but I get an "attribute error: 'module' object has no attribute 'run'.
Should I call another library?


RE: Echo call to VLC bash using subprocess.Popen on Linux - Gribouillis - Jan-03-2019

subprocess.run() is new in python 3.5. Can you upgrade to this version? Hmm. Actually, the capture_output parameter is new in 3.7. You could perhaps simply use the communicate() method.i
p = subprocess.Popen("echo " + cmd + " | nc -U " + Socket1Location, shell = True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
out, err = p.communicate()



RE: Echo call to VLC bash using subprocess.Popen on Linux - LuukS001 - Jan-03-2019

When I use communicate() the script hangs, just like when I use stdout.read()...
This is the script:

p = subprocess.Popen(['vlc -I oldrc --rc-unix=/home/user/Documents/Sockets/socket1.sock'], shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
out, err = p.communicate()

p = subprocess.Popen(['echo enqueue /home/user/Documents/DualscreenVLC/videos/MVI_2534.MP4 } nc -U /home/user/Documents/Sockets/socket1.sock'], shell = True, stdout = subprocess.PIPE, stderr = subprocess.PIPE)
out, err = p.communicate()
I can try upgrading to python 3.5 tomorrow but it maybe it is related to the operating system as I am not finding this issue anywhere else...


RE: Echo call to VLC bash using subprocess.Popen on Linux - Gribouillis - Jan-03-2019

There is an old code that I used in Linux for certain cases when stdout blocks with subprocess. It uses socketpair() and select(). Here is an example involving two scripts a.py and b.py (launched by a.py which reads its output), but it also works when the second process is not a python program. I already posted this in other forums but I think it's a nice trick to know
##################################
# a.py

import subprocess
import socket
import select

esock, echildsock = socket.socketpair()
osock, ochildsock = socket.socketpair()
p = subprocess.Popen(['python3','b.py'], 
    stderr=echildsock.fileno(),
    stdout=ochildsock.fileno())

while p.poll() is None:
    r, w, x = select.select([esock, osock],[],[], 1.0)
    if not r:
        continue # timed out
    for s in r:
        print('stdout ready' if s is osock else 'stderr ready')
        data = s.recv(1024)
        print('received', data.decode('utf8'))
osock.shutdown(socket.SHUT_RDWR)
osock.close()
esock.shutdown(socket.SHUT_RDWR)
esock.close()
##################################
# b.py

res = input('???')
print('in b:', res)



RE: Echo call to VLC bash using subprocess.Popen on Linux - LuukS001 - Jan-04-2019

Thank you, that looks great.

If I understand it well, I can replace asock and osock with the vlc socket locations.
And I can add the echo commands to the input in b.py so it will be send to both sockets?
Does for s in r: mean that the p.poll() command iterates through b.py?


RE: Echo call to VLC bash using subprocess.Popen on Linux - Gribouillis - Jan-04-2019

Quote:If I understand it well, I can replace asock and osock with the vlc socket locations.

No, only replace the call to Popen() at line 10-12 with your command:
p = subprocess.Popen("echo " + cmd + " | nc -U " + Socket1Location,
    shell = True, 
    stderr=echildsock.fileno(),
    stdout=ochildsock.fileno())
Quote:Does for s in r: mean that the p.poll() command iterates through b.py?
No while p.poll() is None iterates while the process p is running. Perhaps you don't know the select command. The call to select() blocks until there is something to read in the sockets esock or osock which are connected to p's error and output streams. It returns a list of sockets that are ready, so r can be [esock] or [osock] or [esock, osock]. The for s in r reads the data from the sockets that have something to receive. I added a timeout of 1 second in select() so that every one second, if there is nothing to read, a.py checks if process p is still alive.


RE: Echo call to VLC bash using subprocess.Popen on Linux - LuukS001 - Jan-06-2019

Thank you very much, that makes sense.
I have been trying to implement it but without the shell=true flag I get this error:
OSError: [Errno 2] No such file or directory
When I split the command into:
(['vlc','-I oldrc --rc-unix=/home/user/Documents/Sockets/socket1.sock'],stderr=echildsock.fileno(), stdout=ochildsock.fileno())
The error is mitigated but no socket is opened. (I tried every combination of splitting the command).

When I do add the shell=True command the code hangs at the stdout again except when I add a 'break' to the while loop. An instance of VLC loads but the echo calls don't seem to communicate with vlc.


RE: Echo call to VLC bash using subprocess.Popen on Linux - Gribouillis - Jan-06-2019

You could perhaps simply remove the echo command and write directly to the nc command stdin
p = subprocess.Popen(["nc", "-U ", Socket1Location], stdin = subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
out, err = p.communicate(input=b'play')