python - 无法从外部进程读取 PTY(伪终端文件)
问题描述
我正在打开一个 PTY(在 Python/Linux 中)并写信给它。我可以通过minicom
完美地阅读它。但是,我无法在另一个 Python(或 C++)程序中读取它。这是一个最小化的示例:
producer.py(打开 pty / 写入它):
import os, sys
from time import sleep
master_fd, slave_fd = os.openpty()
print "minicom -D %s" % os.ttyname( slave_fd )
for i in range(0,30):
d = str(i % 10)
os.write( master_fd, d )
sys.stdout.write( d )
sys.stdout.flush()
sleep( 2 )
os.close( slave_fd )
os.close( master_fd )
print "\nDone"
consumer.py(尝试打开/读取):
import os, sys
from time import sleep
pts=raw_input("Enter pts number:")
while True:
fd=0
try:
fd=os.open('/dev/pts/%d' % (pts,),
os.O_RDONLY | os.O_NONBLOCK )
sys.stdout.write( os.read(fd, 1 ) )
sys.stdout.flush()
except Exception as e: print e
if fd: os.close(fd)
sleep(1)
读取的结果总是:
[Errno 11] 资源暂时不可用
如果我以阻塞模式阅读,它只会阻塞,直到生产者终止。然后,它说该文件不存在。
我花了几天时间尝试设置各种模式、权限、锁等,但似乎没有什么能让我到任何地方。这种事情很容易与常规文件一起工作。另外,请再次注意minicom 可以毫无障碍地读取 pty。此外,使用lsof
我可以看到 minicom 和我的 consumer.py 脚本确实打开了文件——这只是在 python 示例中不起作用的读取。那么minicom的秘密是什么?我尝试在 minicom 源代码中找到这样的东西,但我没有成功找到我可以使用的任何东西。
理想情况下,我的制作人会使其易于打开和阅读(就像在我的消费者示例中一样),但如果我能看到这项工作,我愿意修改任何一端......
解决方案
是什么让您认为您无法打开 PTY?您的代码中没有任何内容提供有关哪个系统调用失败的信息。
最可能的情况是os.read()
调用失败并显示错误代码EAGAIN
(aka EWOULDBLOCK
),因为您已在非阻塞模式下打开 PTY。没有要读取的数据,因为 PTY 是 tty,并且 tty 最初处于“熟”模式,这意味着在发送行尾字符或某些中断字符之前,不会将任何输入传递给消费者。Minicom 可能会通过 termios 调用将 pty 置于“原始”模式,您也应该这样做。
我猜您并不想将 PTY 置于非阻塞模式。除非您设置事件轮询或选择循环,否则您将反复收到EAGAIN
“错误”(这不是真正的错误),并且您真的不想在重试之前等待整整一秒钟。(您也不是真的想关闭并重新打开 PTY。)建议您将 PTY 留在阻塞模式,但将其配置为在每次击键时立即返回(再次,使用termios
)。
推荐阅读
- angular - Angular 应用程序未在 Safari 上加载,但可在 chrome 中使用
- python - Python:“浮动”对象不可下标
- oracle - 如何转义字符串中的单引号?
- python-3.x - 如何从不和谐服务器获取所有用户?
- postgresql - 在选定的时间间隔来自 PostgreSQL 数据库的数据
- python - 代码未执行,但也未显示任何错误
- eclipse-rcptt - 在 RCPTT 中使用数据绑定时,单击单选按钮不会更新布局
- python - IOError:[Errno 13] 权限被拒绝 Pandas
- c++ - MSB6006:“CL.exe”在使用 openMP 时以代码 2 退出
- sql-server - 将单行拆分为多行 - SQL Server Management Studio 2018