获取 shell 脚本以等待来自 python 程序的特定响应
Getting a shell script to wait for a specific response from python program
我正在尝试编写一个调用 python 程序的脚本,暂停直到程序输出特定消息(而不是程序结束时),然后继续。
如果我有 example.py 这样的 运行 无限期:
doSomething()
print('I did something')
doSomethingElseForever()
我想要这样的脚本:
echo "Running python program"
python3 example.py &
waitForOutput("I did something")
echo "Python program did something, it's still running in the background"
doSomeMoreScriptStuff
理想情况下,我会 运行 脚本,它会启动 example.py,暂停直到 example.py 输出“我做了某事”,然后继续启动更多程序或其他, 没有停止 example.py (因此 &)。
我在 Ubuntu 顺便说一句。
编辑:我认为目前在我的特定应用程序中我可以更改我的 python 脚本来创建一个文件而不是 print(),但为了学习(并且因为这看起来像复杂的做事方式),让我们假设我无法编辑 python 文件。所以我所要做的就是 print() 语句的已知输出。
您可以使用 pexpect
执行此操作。我启动了一个线程,它调用 pexpect.spawn()
到 运行 你的子脚本。它等待您想要的输出,然后设置一个事件,以便主程序知道事件已经发生。然后它等待子程序退出,这反过来又允许主程序退出:
#!/usr/bin/env python3
import pexpect
import time
import threading
doneIt = threading.Event()
def childHandler():
"""Spawns the child and manages its output"""
global doneIt
print('HANDLER: Spawning child')
child = pexpect.spawn('./example.sh')
print('HANDLER: Child spawned, waiting for it to do something')
child.expect('I did something')
doneIt.set()
print('HANDLER: Waiting for child to finish')
child.expect(pexpect.EOF)
print('HANDLER: Done')
if __name__ == "__main__":
print('MAIN: Starting')
cH = threading.Thread(target=childHandler)
cH.start()
# Wait for event and do other stuff, like printing
while True:
print('MAIN: waiting for child to do something')
if doneIt.wait(1):
break
print('MAIN: Continuing...')
# Wait till childHandler exits before exiting
cH.join()
print('MAIN: Exit')
我用这个 example.sh
作为您调用的 Python 脚本的模型:
#!/bin/bash
LOG="run.txt"
date +'Running: %H:%M:%S' > "$LOG"
for ((i=8;i>0;i--)) ; do
date +'Running: %H:%M:%S' >> "$LOG"
sleep 1
done
date +'SUCCESS: %H:%M:%S' >> "$LOG"
echo "I did something"
for ((i=1;i<10;i++)) ; do
date +'Continuing: %H:%M:%S' >> "$LOG"
sleep 1
done
date +'DONE: %H:%M:%S' >> "$LOG"
这是日志:
Running: 13:05:27
Running: 13:05:27
Running: 13:05:28
Running: 13:05:29
Running: 13:05:30
Running: 13:05:31
Running: 13:05:32
Running: 13:05:33
Running: 13:05:34
SUCCESS: 13:05:35
Continuing: 13:05:35
Continuing: 13:05:36
Continuing: 13:05:37
Continuing: 13:05:38
Continuing: 13:05:39
Continuing: 13:05:40
Continuing: 13:05:41
Continuing: 13:05:42
Continuing: 13:05:43
DONE: 13:05:44
我正在尝试编写一个调用 python 程序的脚本,暂停直到程序输出特定消息(而不是程序结束时),然后继续。
如果我有 example.py 这样的 运行 无限期:
doSomething()
print('I did something')
doSomethingElseForever()
我想要这样的脚本:
echo "Running python program"
python3 example.py &
waitForOutput("I did something")
echo "Python program did something, it's still running in the background"
doSomeMoreScriptStuff
理想情况下,我会 运行 脚本,它会启动 example.py,暂停直到 example.py 输出“我做了某事”,然后继续启动更多程序或其他, 没有停止 example.py (因此 &)。
我在 Ubuntu 顺便说一句。
编辑:我认为目前在我的特定应用程序中我可以更改我的 python 脚本来创建一个文件而不是 print(),但为了学习(并且因为这看起来像复杂的做事方式),让我们假设我无法编辑 python 文件。所以我所要做的就是 print() 语句的已知输出。
您可以使用 pexpect
执行此操作。我启动了一个线程,它调用 pexpect.spawn()
到 运行 你的子脚本。它等待您想要的输出,然后设置一个事件,以便主程序知道事件已经发生。然后它等待子程序退出,这反过来又允许主程序退出:
#!/usr/bin/env python3
import pexpect
import time
import threading
doneIt = threading.Event()
def childHandler():
"""Spawns the child and manages its output"""
global doneIt
print('HANDLER: Spawning child')
child = pexpect.spawn('./example.sh')
print('HANDLER: Child spawned, waiting for it to do something')
child.expect('I did something')
doneIt.set()
print('HANDLER: Waiting for child to finish')
child.expect(pexpect.EOF)
print('HANDLER: Done')
if __name__ == "__main__":
print('MAIN: Starting')
cH = threading.Thread(target=childHandler)
cH.start()
# Wait for event and do other stuff, like printing
while True:
print('MAIN: waiting for child to do something')
if doneIt.wait(1):
break
print('MAIN: Continuing...')
# Wait till childHandler exits before exiting
cH.join()
print('MAIN: Exit')
我用这个 example.sh
作为您调用的 Python 脚本的模型:
#!/bin/bash
LOG="run.txt"
date +'Running: %H:%M:%S' > "$LOG"
for ((i=8;i>0;i--)) ; do
date +'Running: %H:%M:%S' >> "$LOG"
sleep 1
done
date +'SUCCESS: %H:%M:%S' >> "$LOG"
echo "I did something"
for ((i=1;i<10;i++)) ; do
date +'Continuing: %H:%M:%S' >> "$LOG"
sleep 1
done
date +'DONE: %H:%M:%S' >> "$LOG"
这是日志:
Running: 13:05:27
Running: 13:05:27
Running: 13:05:28
Running: 13:05:29
Running: 13:05:30
Running: 13:05:31
Running: 13:05:32
Running: 13:05:33
Running: 13:05:34
SUCCESS: 13:05:35
Continuing: 13:05:35
Continuing: 13:05:36
Continuing: 13:05:37
Continuing: 13:05:38
Continuing: 13:05:39
Continuing: 13:05:40
Continuing: 13:05:41
Continuing: 13:05:42
Continuing: 13:05:43
DONE: 13:05:44