如何将rfcomm shell命令的结果放入Python变量中?

3

我正在使用Python脚本连接蓝牙设备并获取数据,但我想知道此Shell命令的结果以便进行下一步工作。

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)

这段代码是我执行命令时的示例:

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

在shell中,它返回:
Connected /dev/rfcomm0 to XX:XX:XX:XX:XX:XX on channel 1
Press CTRL-C for hangup

但是我该如何将上述结果放入变量中呢?因为我需要知道此命令的结果。我在子进程中使用stdout、stderr,但它不起作用。我正在使用Python 2.7。 Python subprocess和用户交互讨论了通常情况下如何将输出存储到变量中,但是我的问题与rfcomm有关,它不会将其结果存储到变量中。当我运行这些脚本时,它们可以正常工作,但是使用rfcomm命令时却不能正常工作。

您希望实现什么样的结果呢?您想让“已连接 /dev/rfcomm0 至 XX:XX:XX:XX:XX:XX 位于通道 1”的内容成为一个变量吗? - johnashu
是的,我需要将这个结果或任何结果放入一个变量中,例如错误结果。 - Ali
你可以使用 my_Variable = stdout 进行操作。 - johnashu
可能是 https://dev59.com/FF4b5IYBdhLWcg3w1U3L 的重复问题。 - tripleee
1
可能是 https://dev59.com/PG855IYBdhLWcg3wUCeC 的重复问题。 - tripleee
显示剩余4条评论
2个回答

3
如果您正在使用Python 3.5或更高版本,则可以使用run。这样,您就可以直接访问,如下所示,
result = subprocess.run(["sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1"], stdout=subprocess.PIPE)

然后像这样访问您想要的内容,
result.stdout

如果你使用的是Python 2.7,建议按照我提供的文档,将你重定向到"旧版高级API"部分。从那里开始,你会注意到可以使用"check_output"。
result = subprocess.check_output(["sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1"])

请注意,如果您想捕获错误,也请使用stderr=subprocess.STDOUT标志。
result = subprocess.check_output("sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1", stderr=subprocess.STDOUT, shell=True)

最后,有一件重要的事情需要您知道:

默认情况下,此函数将返回编码字节数据。输出数据的实际编码可能取决于所调用的命令,因此文本解码通常需要在应用程序级别处理。

编辑

由于您的目标似乎是在运行时获取输出,请查看答案。我更喜欢链接而不是重新发明轮子。


实际上,我正在使用Python 2.7。 - Ali
runcheck_output只有在rfcomm完成后才会结束。我的印象是OP希望该进程保持运行并与其交互。 - tripleee
@tripleee 是的,我现在明白了。谢谢你的见解。我在我的编辑中添加了一个解决方案链接。 - scharette
确实,但正确的做法是将此问题指定为重复。 - tripleee

1

在数据返回之前,您可能需要发出CTRL+C命令。

发送信号并捕获异常以处理返回的内容。

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)

我运行了你的代码,但是使用这个脚本后,它会在“已连接 /dev/rfcomm0 到 00:13:EF:C0:01:79 在通道1上,请按CTRL-C挂断”之后等待,而不会执行“设备已准备好”命令和其他命令。 - Ali
你把 while 循环删除了吗? - johnashu
我准确地运行了你的代码,它在运行 "p = subprocess.Popen("sudo rfcomm connect /dev/rfcomm0 XX:XX:XX:XX:XX:XX 1",shell=True)" 后返回 Connected /dev/rfcomm0 to 00:13:EF:C0:01:79 on channel 1 Press CTRL-C for hangup" 并无限等待。 - Ali
如果您删除了p.wait()这行代码会发生什么? - johnashu
我删掉了那一行,然后就跟之前一样了。 - Ali

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接