【问题标题】:pexpect can't pass input over 1024 chars?pexpect 不能传递超过 1024 个字符的输入?
【发布时间】:2012-02-09 20:46:24
【问题描述】:

我目前正在使用以下代码将一些输入传递给具有 pexpect 的进程:

p = pexpect.spawn('cat', timeout=5.0 )
p.maxread = 5000
p.setecho(False) # prevent the process from echoing stdin back to us
INPUT_LEN = 1024
p.sendline('a'*INPUT_LEN)
print p.readline() # pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().

当 INPUT_LEN 对于 >= 1024 个字符,进程不会收到完整的输入,导致 p.readline() 上出现“pexpect.TIMEOUT”错误.

我尝试将我的输入分成小于 1024 个字符的部分,但这也有同样的问题:

p = pexpect.spawn('cat', timeout=5.0 )
p.maxread = 5000
p.setecho(False)
INPUT_LEN = 1024
p.send('a'*1000)
p.sendline('a'*(INPUT_LEN-1000))
print p.readline() # pexpect.TIMEOUT: Timeout exceeded in read_nonblocking().

有谁知道如何让 pexpect 处理超过 1024 个字符的输入?我尝试查看源代码,但它似乎只是在调用 os.write(...)。

(作为旁注,我注意到当我从 shell 运行“cat”并尝试使用“Cmd+V”粘贴 >=1024 个字符时,会发生相同的截断错误。但是,如果我一切正常运行“pbpaste | cat”。)

谢谢!

更新: 调用“os.write()”返回1025,表示写入成功,但是os.read()返回“\x07”(单字符BEL),然后在下一次调用时挂起,导致超时。

将 os.write() 调用分成两个 1024 字节以下的 write(),由调用 os.fsync() 分隔,不会改变任何内容。

【问题讨论】:

  • pexpect.spawn 应该有一个maxdata 关键字默认设置为2000,所以这可能不适用于您的情况,但是您是否尝试过增加它?
  • 不幸的是,这不起作用;查看最新编辑
  • 对不起,我写了maxdata,但我的意思是maxread,我想这值得一试。
  • 深入挖掘源代码我发现它使用了ptyfcntl,这可能是您的1024 缓冲区限制的根源。能否提供python版本和平台?
  • python 版本是“Python 2.7”,平台是 OSX 10.6.8(“Darwin tba.local 10.8.0 Darwin Kernel Version 10.8.0: Tue Jun 7 16:33:36 PDT 2011;根:xnu-1504.15.3~1/RELEASE_I386 i386")

标签: python macos io expect pexpect


【解决方案1】:

你的问题好像和MacOS有关,看看MacOSX 10.6.7 cuts off stdin at 1024 chars

它基本上说 1024 是你的 tty 缓冲区限制。

我不是 Mac OS 方面的专家,但也许其他人可以为您提供更多相关信息。

【讨论】:

  • 关于如何在 python 级别解决此问题的任何建议?例如通过写入 1023 个字节,刷新缓冲区,然后写入其余部分?
  • @tba:根据您的解释,问题似乎在阅读方面。因此,我认为您使用管道方法(就像 pbpaste 所具有的方法一样),但我担心这可能会使您使用 pexpect 的努力无效。
  • 不幸的是,使用带有 python 的“子进程”的管道会导致死锁:请参阅docs.python.org/library/subprocess.html 上关于使用“.stdin.write”的“警告:”。建议的解决方法是使用communicate(),它等待进程终止。这对我不起作用,因为我需要在进程终止之前多次发送和接收信息。
  • @tba:如果您需要来回发送/接收,请不要使用communicate(),但不要让警告吓到您太多:您可以使用stdin.write/@987654328 @,你“只是”需要小心。在 Unix 上,您有 select(看看 this answer),而对于跨平台解决方案(也称为 Windows),您必须使用 @987654330 @(看看this other answer)。
  • 谢谢瑞克。我之前尝试过 stdin.write 和 stdin.read 但遇到死锁,因此切换到 pexpect。知道如何调试死锁吗?
【解决方案2】:

我意识到已经很晚了,但是我正在为遇到同样问题的人发布一个解决方案(就像我今天早些时候所做的那样)。

基于一些答案/cmets,我编写了一个类似 pexpect 的包,它使用 stdin.write 和 stdout.read 而不是 pexpect 使用的任何东西。我还没有机会非常彻底地测试它,但到目前为止,它已经经受住了挑战。

您可以在这里找到代码:https://github.com/tayyabt/tprocess

【讨论】:

    【解决方案3】:

    在我的情况下(Debian Linux),限制(4096 个字符)与终端的规范处理输入模式有关。在pexpect documentation中有一些关于这个的cmets。

    我通过在发送数据之前关闭佳能模式解决了我的问题:

    p.sendline('stty -icanon')
    p.sendline('a'*5000)
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-12-31
      • 2015-05-09
      • 2019-04-15
      • 1970-01-01
      • 2012-06-18
      相关资源
      最近更新 更多