Python: start bach file and read output until specific line appear and continue

时间:2019-04-08 13:03:28

标签: python subprocess

So i have batch file that start appium server.

When i start execute my batch file i want to read the output and when the server running i want to continue.

I know when appium server running from this output:

Appium REST http interface listener started on 0.0.0.0:4723

Currently this is what i have:

process = subprocess.Popen([r'C:\\appium.bat'])
stdout = process.communicate()[0]
print('STDOUT:{}'.format(stdout))

What i want is to wait up to 60 seconds or until this line appears. In case 60 secods pass and this line (Appium REST http interface listener started on 0.0.0.0:4723) did not appear i want to raise exception.

My problem is that when my server started the process is continue to run so this never exit and continue to the next code and i cannot kill the appium process.

Any suggestions how to solve it ?

3 个答案:

答案 0 :(得分:1)

You can wait by using the time module

import time

time.sleep(60) # wait for 60 seconds

答案 1 :(得分:1)

The following code should work for your case. First, it spawns a process, and wait for the timeout, while waiting, it will keep checking the output of the process. Then when the pattern is matched, it will break, or else Exception will be raised.

import time
import subprocess
import re


proc = subprocess.Popen(['/tmp/test.sh'], stdout=subprocess.PIPE)

timeout = time.time() + 10 # adjust the timeout value here
target = ".*started on .*"

while True:
    if time.time() >= timeout:
        raise Exception("Server wasn't started")
    else:
        output = proc.stdout.readline()
        # read a line of input

        if output == '' and proc.poll() is not None:
            # process is not running anymore, 
            # proc.poll() will return None if process is still running
            raise Exception("Server process has stopped")
        else:
            line = output.decode().strip()
            if re.match(target, line):
                # if the pattern is matched, do something and break
                print("Server has started")
                break
            time.sleep(0.5)

This is the bash file I used to test. Save it as /tmp/test.sh

#!/bin/bash

echo "TEST"
sleep 1
echo "server has started on 0.0.0.0"

答案 2 :(得分:0)

You could do this with signal.alarm,

import signal
import time
import subprocess

def handler(signum, stack):
    raise Exception("It didn't happen in time...") # raise exception if it didn't come up within the time frame 

signal.signal(signal.SIGALRM, handler)
signal.alarm(60)
process = subprocess.Popen([r'C:\\appium.bat'])
stdout = process.communicate()[0] # assuming this blocks
print('STDOUT:{}'.format(stdout))
signal.alarm(0) # turn of the alarm, if it came up within 60 seconds

if .communicate() is not blocking, then,

import subprocess
process = subprocess.Popen([r'C:\\appium.bat'])
stdout = process.communicate()[0] # non blocking ?
print('STDOUT:{}'.format(stdout))
time.sleep(60)
if 'Appium REST http interface listener started' not in stdout:
    raise Exception("It didn't come up in time...")