python---命令行程序的自动交互

keywords: python 命令行程序 自动化 交互

以这个python程序为例:

# coding:utf8
# python3

import random

first_num = str(random.randint(0, 10))
second_num = str(random.randint(0, 10))

first_input = input('input {}: '.format(first_num))
second_input = input('input {}: '.format(second_num))

if first_num==first_input and second_num==second_input:
    print('Right!')
else:
    print('Wrong!')

用脚本调用这个程序,并自动输出 'Rignt!',使用 subprocess 实现:

# coding:utf-8
# python3

import sys
import re
import subprocess
from threading import Thread


class ProcessInteraction:
    process = None

    def __init__(self, command):
        self.process = subprocess.Popen(
            command, stdin=subprocess.PIPE, stdout=subprocess.PIPE)

    def __del__(self):
        self.process.stdin.close()
        self.process.stdout.close()

    def recvline(self):
        return self.process.stdout.readline().decode('utf8')

    def recv_n(self, n):
        return self.process.stdout.read(n).decode('utf8')

    def recvuntil(self, want_end_str):
        current_str = ''
        while True:
            current_str += self.recv_n(1)
            if current_str.endswith(want_end_str):
                return current_str

    def recvuntil_re(self, want_re_str):
        current_str = ''
        while True:
            current_str += self.recv_n(1)
            s = re.search(want_re_str, current_str)
            if s:
                return [current_str, s]

    def send(self, send_str):
        final_bytes = send_str.encode('utf8')
        self.process.stdin.write(final_bytes)
        self.process.stdin.flush()

    def sendline(self, send_str):
        self.send(send_str+'\n')
    
    def interact(self):
        def recv_loop():
            while True:
                c = self.recv_n(1)
                # print 写到控制台会有延时,直接用系统io写
                sys.stdout.write(c)
                sys.stdout.flush()

        def send_loop():
            while True:
                send_str = input()
                self.sendline(send_str)

        recv_thread = Thread(target=recv_loop)
        send_thread = Thread(target=send_loop)

        recv_thread.start()
        send_thread.start()

        recv_thread.join()
        send_thread.join()


command = ['py', '-3', 'want_right.py']

pi = ProcessInteraction(command)
for i in range(2):
    content = pi.recvuntil_re(r'input (\d+): ')
    print(content[0])
    num = content[1].group(1)
    print(repr(num))
    pi.sendline(num)
content = pi.recvline()
print(content)

注意:如果在 linux 下执行,command 需要修改为 ['python3', 'want_right.py']

输出:

input 5:
'5'
input 0:
'0'
Right!

感谢 zl

20200525

posted @ 2020-05-25 22:42  rvy  阅读(652)  评论(0编辑  收藏  举报