3

I am using this script in python in order to connect to a Bluetooth device and then get data, but I want to know the result of this shell command in order to do next works

import os
import time
import signal
import subprocess


p = subprocess.Popen("sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1",shell=True)
(stderr,stdout) = p.communicate()
print 'stderr: [%s]' % stderr
print 'stdout: [%s]' % stdout
time.sleep(5)
while True:
     print "Device is ready"
     time.sleep(5)

this code is a sample when I run the command:

"sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1" 

in shell, it returns:

Connected /dev/rfcomm0 to XX:XX:XX:XX:XX:XX on channel 1
Press CTRL-C for hangup

but how can I put above result in a variable, because I need to know the result of this command? I use stdout, stderr in subprocess but does not work. I am using python 2.7

Python subprocess and user interaction

above link talk about getting output in a variable in general, but the problem in my question related to rfcomm, which does not put its result in variable, I run those script and they works well, but it does not works when it used with rfcomm command

Ali
  • 602
  • 6
  • 18
  • What is the desired result? you want `Connected /dev/rfcomm0 to XX:XX:XX:XX:XX:XX on channel 1` to be a variable? – johnashu Jul 13 '18 at 12:49
  • yes, I need to put this result or any result, for example, error results put in a variable – Ali Jul 13 '18 at 12:50
  • you can just do `my_Variable = stdout` – johnashu Jul 13 '18 at 12:51
  • Possible duplicate of [Python subprocess and user interaction](https://stackoverflow.com/questions/14457303/python-subprocess-and-user-interaction) – tripleee Jul 13 '18 at 13:35
  • Possible duplicate of https://stackoverflow.com/questions/28616018/multiple-inputs-and-outputs-in-python-subprocess-communicate – tripleee Jul 13 '18 at 13:44
  • 1
    Possible duplicate of https://stackoverflow.com/questions/4417546/constantly-print-subprocess-output-while-process-is-running – tripleee Jul 13 '18 at 13:45
  • @tripleee, I check that links but those not give my answer exactly, but thanks for introducing that link – Ali Jul 13 '18 at 13:54
  • @tripleee your mentioned links talks about getting output in a variable in general, but the problem in my question related to rfcomm, which does not put its result in variable, I run those script and they works well, but it does not works when it used with rfcomm command – Ali Jul 13 '18 at 14:36
  • It probably prints to standard error rather than standard output. The general principle is independent of the command you are running but there are minor complications like this. – tripleee Jul 13 '18 at 15:29

2 Answers2

3

If you're using Python 3.5 or higher, you can use run instead. That way you'll have access directly like so,

result = subprocess.run(["sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1"], stdout=subprocess.PIPE)

Then access what you want like this,

result.stdout

If ever you use Python 2.7, as suggested by documentation I linked, they redirect you to the Older high-level API section. From there you'll notice that you could use check_output

result = subprocess.check_output(["sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1"])

Note, if ever you want to catch error also use the stderr=subprocess.STDOUT flag.

result = subprocess.check_output("sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1", stderr=subprocess.STDOUT, shell=True)

Lasty, there is an important not you should be aware,

By default, this function will return the data as encoded bytes. The actual encoding of the output data may depend on the command being invoked, so the decoding to text will often need to be handled at the application level.

EDIT

Since your goal seems to get output while running. Take a look at this answer. I prefer linking instead of re-inventing the wheel.

scharette
  • 9,437
  • 8
  • 33
  • 67
1

You may need to issue the CTRL+C command before the data is returned.

Send a signal and catch the exception to deal with what is returned.

import os
import time
import signal
import subprocess


stream = []
try:
    p = subprocess.Popen("sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1",shell=True)
    #(stderr, stdout) = p.communicate()

    #print 'stderr: [%s]' % stderr
    #print 'stdout: [%s]' % stdout
    #time.sleep(5)
    #print "Device is ready"

    time.sleep(5)

    os.kill(p.pid, signal.CTRL_C_EVENT)
    p.wait()

except KeyboardInterrupt:                
#except Exception: 
    for line in p.stdout: #May also be p.stderr
        stream.append(line)                         

    for x in stream:                    
        print(x)
johnashu
  • 2,167
  • 4
  • 19
  • 44
  • I run your code, but with this script, it waits after "Connected /dev/rfcomm0 to 00:13:EF:C0:01:79 on channel 1 Press CTRL-C for hangup " and does not go to "Device is ready" command and others. – Ali Jul 13 '18 at 13:05
  • did you take out the `while` loop? – johnashu Jul 13 '18 at 13:07
  • I exactly run your code and it after runs the "p = subprocess.Popen("sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1",shell=True)" it returns Connected /dev/rfcomm0 to 00:13:EF:C0:01:79 on channel 1 Press CTRL-C for hangup " and waits for infinite – Ali Jul 13 '18 at 13:09
  • what happens if you take out the line `p.wait()`? – johnashu Jul 13 '18 at 13:11
  • I took out that line and not happened. same as before – Ali Jul 13 '18 at 13:14