Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/python-3.x/19.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 3.x 如何从pexpect.spawn()收集所有输出_Python 3.x_Pexpect - Fatal编程技术网

Python 3.x 如何从pexpect.spawn()收集所有输出

Python 3.x 如何从pexpect.spawn()收集所有输出,python-3.x,pexpect,Python 3.x,Pexpect,目前,c.read()函数只返回我正在调用的程序的输出值,不收集交互部分中发生的内容。(换句话说:等待用户名和密码)。由于错误可能发生在该部分中,因此我需要在调用cmd之后收集所有输出 使用run命令可以很好地工作。我正在尝试转换为使用expect.spawn(),因为它看起来非常接近expect的ssh版本。当前run()方法在本地工作,因此工作正常。我找不到将返回整个输出的getOutput()类型函数 import pexpect class Expect( ): def Do(

目前,c.read()函数只返回我正在调用的程序的输出值,不收集交互部分中发生的内容。(换句话说:等待用户名和密码)。由于错误可能发生在该部分中,因此我需要在调用cmd之后收集所有输出

使用run命令可以很好地工作。我正在尝试转换为使用expect.spawn(),因为它看起来非常接近expect的ssh版本。当前run()方法在本地工作,因此工作正常。我找不到将返回整个输出的getOutput()类型函数

import pexpect
class Expect( ):
    def Do( self, cmd, program: list = [], timeout: int = 20 ):
        # result = run( cmd, events=program, timeout=timeout).decode() 

        result = ''
        c = pexpect.spawn( cmd, encoding='utf-8', timeout=timeout )
        for curItem in program:
            # print( 'wait: ' + curItem[0] + ' resp: ' + curItem[1])
            c.expect( curItem[0] )
            c.sendline( curItem[1] )
            # result += c.read()
    
        result += c.read()

        print ( 'res: ' + str(result) )
        return result


cmd  = 'fmsadmin list files -s'
prog = [('username \\(.+\\):', 'yourUN\n'), ('password:', 'yourPW\n')]
res  = Expect().Do( cmd, prog )    # Returns everything
# use results to verify functionality
结果

ID File                  Clients Size   Status Enabled Extended Privileges                                                                   Encrypted 
1  FMServer_Sample.fmp12 0       905216 Normal fmapp fmxml fmphp fmwebdirect                                                                 No        
当我期待时

username (yourUN):yourUN
password:
ID File                  Clients Size   Status Enabled Extended Privileges                                                                   Encrypted 
1  FMServer_Sample.fmp12 0       905216 Normal fmapp fmxml fmphp fmwebdirect                                                                 No        
更新

我在c.sendline(curItem[1])下面添加了result+=c.before+c.after,现在返回: c、 发送线(curItem[1])

不幸的是,还有两个问题。1输出中有其他值,例如返回值,如果我提供了无效密码,我将返回调试详细信息,而不返回应用程序返回的值。我得到:

before (last 100 chars): '\r\n/usr/local/bin/fmsadmin: Permission denied, please try again.\r\nusername (yourUN):'
after: <class 'pexpect.exceptions.TIMEOUT'>
match: None
match_index: None
etc
before(最后100个字符):'\r\n/usr/local/bin/fmsadmin:权限被拒绝,请重试。\r\n用户名(yourUN):'
之后:
匹配:无
匹配索引:无
等

因此,简而言之,我要从CLI中查找完整的返回值,就像手动返回一样。这就是run()所做的。

Pexpect,就像最初的TCL Expect一样,要获得会话输入和输出的正确部分有点棘手。挑战在于如何设置搜索模式的格式以匹配它应该匹配的内容,并且仅此而已。要使其正常工作,您只需使用
匹配
属性来解析

也就是说,Pexpect获取终端显示的所有内容,包括命令和输出。幸运的是,没有显示密码,因此,不幸的是,Pexpect无法看到它们

from pexpect import spawn, EOF  # Better import only needed methods
process = spawn('bash', encoding='utf-8')
process.expect('$')             # Expects terminal prompt

process.sendline('read -p "username: " var')
process.expect('\nusername: ')  # Gets command, newline and username prompt
process.sendline('me')
process.expect('[^\n]*\n.*$')   # Gets typed string, newlind and terminal prompt
print(process.match.group(0))   # Prints whole string matched
me                              # User typed
me@myhost ~ $                   # Terminal prompt

process.sendline('read -sp "password: " var')   # Note the '-s' for 'silent'
process.expect('\npassword: ')
process.sendline('my_passwd')
process.expect('.*$')           # Trying to match a newline just doesn't work
print(process.match.group(0))
me@myhost ~ $                   # Only terminal prompt

process.sendline('exit')
process.expect(EOF)
所以你应该知道你想解决什么样的问题。为什么要收集发送和返回的所有信息,包括密码

顺便说一句,您可能已经知道代码中的普通密码存在问题。我的建议:
getpass

from getpass import getpass
password = getpass()
<Then use the password>
从getpass导入getpass
密码=getpass()

顺便说一句,为了以防万一,你可以四处看看。

好的,我想出来了。不太符合预期,但这是有道理的。一些变化:

  • 在for循环的末尾添加结果+=c.before+c.after。这抓住了 帐户和密码的输出以及CLI的任何错误 应用程序
  • 将spawn、expect、send放入try-accept块中
  • 将结果+=c.read()移到内部,然后重试,但不包括(使 例外情况)
  • 最后在异常期间调用result+=c.buffer
  • 我可能会在下一个版本中删除本地部分(一旦我弄清楚了远程案例)


    我在for语句的底部添加了:result+=c.before+c.after,但这就像一个hack,它添加了一些额外的返回案例。在我的帐户之后,而不是在密码之后,获取额外的返回值。同时获取run()未返回的不必要的调试详细信息:after:match:None match\u index:None添加c.exitstatus=False或True无法删除调试。我认为这里存在误解。我在让程序运行方面没有问题。它找到并正确响应用户名和密码。不幸的是,我没有得到所有的回复。响应中未包含的帐户名和密码详细信息。后来,我发现提供了一个无效的密码,我从程序中获得了Pexcept的调试信息,而不是CLI的输出。缓冲区中只有部分CLI输出。我重写了原始文章,以包含实际结果和预期结果,以便您可以看到问题。哦,这不是生产代码,所以我不担心帐户详细信息和OMG。自上周四以来,我已经阅读了大约5次文档,因此我非常感谢您的帮助。看来我错过了您的问题。“为什么我要收集所有东西。”我正在测试软件。所以我需要捕获所有信息,以便验证软件是否正确响应。@Keith好吧,我已经尽力理解你的问题了。您说过要收集所有输入和输出,但无法发送密码。我指出了为什么Pexpect在正常使用中不这么做,这是一个安全问题,也是一种更安全的处理方法。但是您的编辑显示您想要的输出没有显示密码,所以我接受您的感觉,我不理解它。@Keith您的问题没有提到这是不会投入生产的测试代码,也没有提到您在我回答之前阅读的文档。所以我想提及安全问题和官方文件会有所帮助。如果你认为这是一个坏主意,请忽略这一部分-它可能会帮助未来的读者。另外,Pexpect不需要读取发送的所有字节来验证代码。至少我从来没有这样做过——但我知道什么呢?
    from getpass import getpass
    password = getpass()
    <Then use the password>
    
    from pexpect import *
    
    class Expect( ):
        def Do( self, cmd, program: list = [], timeout: int = 20 ):
            local   = False
            result  = ''
            if local:
                result = runu( cmd, events=program, timeout=timeout ) 
            else:
                c = ''
                try:
                    c = spawnu( cmd, timeout=timeout )
                    for curItem in program:
                        c.expect( curItem[0] )
                        c.sendline( curItem[1] )
                        result += c.before + c.after
                    result += c.read()
                except:
                    result += c.buffer
            return result
    
    cmd  = 'fmsadmin list files -s'
    prog = [('username \\(.+\\):', 'yourUN\n'), ('password:', 'yourPW\n')]
    res  = Expect().Do( cmd, prog, 5 )
    print ( '-' * 50 + '\n' + str(res))