python3中的Pexpect interact()异常

时间:2017-05-29 16:24:43

标签: python python-2.7 python-3.x pexpect

我正在学习Python,如果我的问题很天真,请道歉。

我在我的脚本中使用pexpect interact(),它正在使用python2.7。但是当我使用python3或python3.5时,我得到以下错误:

Traceback (most recent call last):
  File "ap_access.py", line 73, in <module>
    child.interact()
  File "/usr/local/lib/python3.5/dist-packages/pexpect/pty_spawn.py", line 745, in interact
    self.__interact_copy(escape_character, input_filter, output_filter)
  File "/usr/local/lib/python3.5/dist-packages/pexpect/pty_spawn.py", line 784, in __interact_copy
    self._log(data, 'read')
  File "/usr/local/lib/python3.5/dist-packages/pexpect/spawnbase.py", line 121, in _log
    self.logfile.write(s)
TypeError: write() argument must be str, not bytes

关于此问题的Google搜索,但实际上没有与interact()相关但没有获得太多信息。

# Script to log into the device and execute the required shell commands.
log_file = open('logfile.txt', 'w')
for ip in list_of_IP_addresses:
        ip1=str(ip)
        child = pexpect.spawnu('ssh '+username+'@'+ip1, log_file)
        code = child.expect(['Are you sure you want to continue connecting   (yes/no)?', 'Please login: ', 'password :', 'No route to host', pexpect.EOF, pexpect.TIMEOUT])

    if code==0:
            child.sendline('yes')
            code = child.expect(['Are you sure you want to continue connecting (yes/no)?', 'Please login: ', 'password :', 'No route to host',  pexpect.EOF, pexpect.TIMEOUT])
    if code==1:
            print("Entering the Username")
            child.sendline(username)
            code = child.expect(['Are you sure you want to continue connecting (yes/no)?', 'Please login: ', 'password :', 'No route to host', pexpect.EOF, pexpect.TIMEOUT])
    if code==2:
            print("Entering the credentials")
            child.sendline(password)
    if code==3:
            print ("Please check for reachability for ip", ip1)
            sys.exit()
    if code==4:
            print ("Looks like there is an error")
            sys.exit(0)
    if code==5:
            print ("Timeout in accessing or logging into ", ip1)
            sys.exit(0)
    child.interact()

如果可以获得有关如何使pexpect interact()与python3.x一起使用的帮助,我将不胜感激

谢谢。

UPDATE

我面临的新问题是在我捕获输出的日志文件中无法看到输出命令如ps,cat输出较大的文件。我尝试使用“setwinsize”设置winsize,将maxreadsize设置为更大的值,但没有任何改变。

def log_separation():
    sep_file = 'Device_LOG_{}.log'.format(date.today())
    child.logfile = open(sep_file, "a")
    with open(sep_file, 'a+') as log_sep:
        log_sep.write('\n'+'\n')

def mem_cpu():
    mem_file = 'Device_LOG_{}.log'.format(date.today())
    with open(mem_file, 'a+') as cpu:
        cpu.write(str(datetime.datetime.now())+'\n')                                                cpu.write('########################################################'+'\n')
child.sendline('top -n 1')
child.expect('#')
log_separation()
child.sendline('cat /proc/meminfo')
log_separation()
child.expect('#')
child.sendline('cat /proc/slabinfo')
log_separation()
child.expect('#')
child.sendline('cat /proc/tasklets')
log_separation
child.expect('#')
child.sendline('free')
log_separation()
child.expect('#')
child.sendline('ps axww')
log_separation()
child.expect('#')
child.sendline('exit')

# Gets the set of all IP addresses in the given range
list_of_IP_addresses = get_IP_address(ip_addr_lower, ip_addr_upper)

#Opening a file to write the error logs to
log_file = open('logfile.txt', 'w')
with open('Device_Access_log.log', 'w+') as f:
# Script to log into the devices and excute the required shell commands.
    for ip in list_of_IP_addresses:
        ip1=str(ip)
        child = pexpect.spawn('ssh '+username+'@'+ip1, logfile=log_file)
        child.logfile_read = sys.stdout
        code = child.expect(['Are you sure you want to continue connecting (yes/no)?', 'Please login: ', 'password :', 'No route to host', pexpect.EOF, pexpect.TIMEOUT])
        if code==0:
            child.sendline('yes')
            code = child.expect(['Are you sure you want to continue connecting (yes/no)?', 'Please login: ', 'password :', 'No route to host',  pexpect.EOF, pexpect.TIMEOUT])
        if code==1:
            print('Entering the Username')
            child.sendline(username)
            code = child.expect(['Are you sure you want to continue connecting (yes/no)?', 'Please login: ', 'password :', 'No route to host', pexpect.EOF, pexpect.TIMEOUT]) 
        if code==2:
        print('Entering the credentials')
        child.sendline(password)
        mem_cpu()
    stats_file = 'Device_LOG_{}.log'.format(date.today())
    with open(stats_file, 'a+') as eol:
        eol.write('############################### End of log for Device '+ip1+' ###############################################'+'\n')
        eol.write('########################################################################################################'+'\n')
    if code==3:
        print ('Ip address error', ip1)
        f.write('No route to host '+ip1+'\n')
    if code==4:
                print ('Error connecting to ', ip1)
        f.write('Error connecting to '+ip1+'\n')
    if code==5:
                print ('Timeout in accessing or logging into ', ip1)
        f.write('Timeout in accessing or logging into '+ip1+'\n')

我可以看到输出直到“free”,ps命令的输出在日志文件中看不到。

2 个答案:

答案 0 :(得分:1)

我找到了问题的解决方案here:如果您将代码的开头更改为:

for ip in list_of_IP_addresses:
    ip1=str(ip)
    child = pexpect.spawnu('ssh '+username+'@'+ip1, logfile=sys.stdout.buffer) # <-- add the logfile keyword here and use sys.stdout.buffer (byte mode) instead of sys.stdout
    ##child.logfile = sys.stdout #<-- comment out this line

它应该工作。注意:我无法完整地测试您的代码。 if个案例对我不起作用,因为我使用ssh键。另外,对我来说键盘回声重复每个字母三次。无论如何,我希望这会对你有所帮助。

修改

我没有找到关于输入类型的三重回显的任何内容,但它与将stdout设置为日志文件这一事实有关。如果您创建了一个日志文件,问题就会消失:

mylogfile = open('logfile.txt', 'wb')
for ip in list_of_IP_addresses:
    ip1=str(ip)
    child = pexpect.spawnu('ssh '+username+'@'+ip1, logfile=mylogfile)
    child.interact()

答案 1 :(得分:0)

我认为我面临同样的问题,但是方式不同。我希望日志文件转到文件。根据我打开它的方式,我会得到一个不同的错误。看哪:

with open("ssh_run.log", "ab") as logfile:
            print( f"Connecting to {self.pxe_user}@{self.pxe_server_ipv4}\n{cmd_2_ssh}" )
            y5: Tuple = pexpect.run( cmd_2_ssh, \
                # (?i) turns on case-insensitive mode
                    events={"(?i)password: ": self.pxe_passwd + "\n"}, \
                    withexitstatus = True, logfile=logfile,
                    timeout = 20 )

我以“ ab”模式打开了日志文件。我收到的错误消息是:

TypeError: a bytes-like object is required, not 'str'

但是,如果我将模式更改为“ a”或“ at”而不是“ ab”,则会得到:

TypeError: write() argument must be str, not bytes

我还尝试了open函数调用的编码参数,但这并不能解决问题。

我正在Ubuntu 18.04上运行python 3.6.9。