I want to run a program using the subprocess module. While running the program, there are cases where it waits for a button press to continue. It is not waiting for this input to the stdin input. The input sent to stdin is ignored by the program. Only when I press a button on the console will the program continue running.
I tried it like this:
proc = Popen("festival.exe level.sok", stdin=PIPE, text=True)
proc.stdin.write('.')
proc.stdin.flush()
It this case nothing happened.
and like this:
proc = Popen...
proc.communicate('.')
In this case, the python code will not continue running until I press a button on the console. If I set a timeout then the python code continues to run but festival.exe does not continue to run.
What should I do to make festival.exe continue running?
P.S.: festival.exe is a solver for sokoban. This case occurs when the given level cannot be solved. E.g.:
########
#.. $ $#
# # #
########
assuming you have the festival program like this:
from random import getrandbits
solved = getrandbits(1)
if solved:
print("executed correctly")
else:
print('a error ocurred')
input('press a button to continue')
exit(1)
you can solve with:
from subprocess import Popen, PIPE
p = Popen(['python3','festival.py'],stdin=PIPE)
p.communicate(input=b'any\n')
Related
I took a piece of code from here:
https://stackoverflow.com/a/10457565/13882705
which is
# I have used os comands for a while
# this program will try to close a firefox window every ten secounds
import os
import time
# creating a forever loop
while 1 :
os.system("TASKKILL /F /IM firefox.exe")
time.sleep(10)
It will terminate a process if it is running using OS module
But if the program did not find the app we mentioned then it prints
ERROR: The process "firefox.exe" not found.
Is there a way to make the program just print application not found once and wait until the program is rerunned?
It is fine even if it just prints "Application Not found"
Use subprocess.run instead of os.system so you have more control:
import subprocess
import time
while True:
proc = subprocess.run(["TASKKILL", "/F", "/IM", "firefox.exe"], stderr=subprocess.PIPE)
if proc.returncode != 0:
print("Application not found.")
break # since application isn't here we just exit
time.sleep(10)
I have some GPU test software i'm trying to automate using python3, The test would normally be run for 3 minutes then cancelled by a user using ctrl+c generating the following output
After exiting with ctrl+c the test can then be run again with no issue
When trying to automate this with subprocess popen and sending SIGINT or SIGTERM i'm not getting the same as if keyboard entry was used. The script exits abruptly and on subsequent runs cant find the gpus (assume its not unloading the driver properly)
from subprocess import Popen, PIPE
from signal import SIGINT
from time import time
def check_subproc_alive(subproc):
return subproc.poll() is None
def print_subproc(subproc, timer=True):
start_time = time()
while check_subproc_alive(subproc):
line = subproc.stdout.readline().decode('utf-8')
print(line, end="")
if timer and (time() - start_time) > 10:
break
subproc = Popen(['./gpu_test.sh', '-t', '1'], stdin=PIPE, stdout=PIPE, stderr=PIPE, shell=False)
print_subproc(subproc)
subproc.send_signal(SIGINT)
print_subproc(subproc, False)
How can I send ctrl+c to a subprocess as if a user typed it?
**UPDATE
import subprocess
def start(executable_file):
return subprocess.Popen(
executable_file,
stdin=subprocess.PIPE,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE
)
def read(process):
return process.stdout.readline().decode("utf-8").strip()
def write(process):
process.stdin.write('\x03'.encode())
process.stdin.flush()
def terminate(process):
process.stdin.close()
process.terminate()
process.wait(timeout=0.2)
process = start("./test.sh")
write(process)
for x in range(100):
print(read(process))
terminate(process)
Tried the above code and can get characters to register with dummy sh script however sending the \x03 command just sends an empty char and doesn't end script
I think you can probably use something like this:
import signal
try:
p=subprocess...
except KeyboardInterrupt:
p.send_signal(signal.SIGINT)
The following solution is the only one I could find that works for windows and is the closest resemblance to sending a Ctrl+C event.
import signal
os.kill(self.p.pid, signal.CTRL_C_EVENT)
I have two .py files on a Raspberry Pi where I am trying to call one file, keep_awake.py, which contains:
import time
import serial
while True:
time.sleep(5)
for option in ["on", "off"]:
for board in ["ACM0", "ACM1"]:
request = serial.Serial(f"/dev/tty{board}", 19200, timeout=1)
for j in [0,1,2,3,4,5,6,7,8,9,"A","B","C","D","E","F"]:
request.write(f"relay {option} {j}\r".encode("utf-8"))
request.close()
time.sleep(.1)
This code is writing to relays to click buttons via wires soldered into the circuit boards. I have tested this code and know that it works. However, when I call it from the parent file like this
subprocess = Popen(["python", "/home/pi/Desktop/DLMW-ART/tools/keep_awake.py"], stdout=PIPE, stderr=STDOUT, universal_newlines=True)
The code does not run.
The purpose of this is to push the devices button so that it stays awake during a firmware update, and then kill the subprocess so it doesn't interfere with the rest of the script. So I want the parent file to look like this:
#Several print statements to let me know where in the script I am
subprocess = Popen(["python", "/home/pi/Desktop/DLMW-ART/tools/keep_awake.py"], stdout=PIPE, stderr=STDOUT, universal_newlines=True)
#Firmware update code will live here
time.sleep(20) #used for testing the call
subprocess.kill()
This code runs in a loop, so I can clearly see the multiple print statements in the main file, but nothing happens in the subprocess, and the devices are not clicked. Am I making the subprocess.Popen call incorrectly?
I have a code snippet in which I run a command in background:
from sys import stdout,exit
import pexpect
try:
child=pexpect.spawn("./gmapPlayerCore.r &")
except:
print "Replaytool Execution Failed!!"
exit(1)
child.timeout=Timeout
child.logfile=stdout
status=child.expect(["[nN]o [sS]uch [fF]ile","",pexpect.TIMEOUT,pexpect.EOF])
if status==0:
print "gmapPlayerCore file is missing"
exit(1)
elif status==1:
print "Starting ReplayTool!!!"
else:
print "Timed out!!"
Here, after the script exits the process in the spawn also gets killed even though it is run in background
How to achieve this?
You are asking the spawned child to be synchronous so that you can execute child.expect(…) and asynchronous &. These don't agree with each other.
You probably want:
child=pexpect.spawn("./gmapPlayerCore.r") # no &
status=child.expect(["[nN]o [sS]uch [fF]ile","",pexpect.TIMEOUT,pexpect.EOF])
child.interact()
where interact is defined as:
This gives control of the child process to the interactive user (the human at the keyboard). …
I have a problem with sub-process code. The subprocess.Popen() works fine but when I try to read its output through stdout.read() there is no value to read.
**import os
import signal
import subprocess
import threading
import sys
import commands
print commands.getoutput("hcitool dev")
print 'down'
commands.getoutput('hciconfig hci1 down')
print 'up'
commands.getoutput('hciconfig hci1 up')
commands.getoutput('killall hcitool')
stop = False
ping = subprocess.call('hcitool lescan', shell = False,
stdout=subprocess.PIPE,executable='/bin/bash')
for i in ping.stdout:
print i
def kill():
global stop
stop = True
os.kill(ping.pid, signal.SIGTERM)
threading.Timer(5, kill).start()
#while not stop:
# print 'now in while not loop'
# sys.stdout.write(ping.stdout.read(1))
print 'trying to print stdout'
out, err = ping.communicate()
print "out",out
#result = out.decode()
print "Result : ",result**
This code works fine when I change hcitool lescan to ping www.google.com, and produces output but when I try with hcitool lescan it either hangs forever or produces no output. Help is appreciated!
Any of the above answers didn't work for me. Was hung up in the forever scan of hcitool. So finally i wrote a shell script and called it by my python code. This is working fine for me and i am reading the output from the file "result.txt".
hcitool lescan>result.txt &
sleep 5
pkill --signal SIGINT hcitool
There are multiple errors in your code e.g., subprocess.call() returns an integer (exit status of the program) and an integer has no .stdout attribute; also the combination of shell=False and non-None executable is very rarely useful (and it is probably used incorrectly in this case).
The simplest way to fix the code is to use check_output():
from subprocess import check_output as qx
output = qx(["hcitool", "lescan"]) # get all output at once
print output,
As an alternative, you could print program's output line by line as soon as its stdout is flushed:
from subprocess import Popen, PIPE
proc = Popen(["hcitool", "lescan"], stdout=PIPE, bufsize=1) # start process
for line in iter(proc.stdout.readline, b''): # read output line-by-line
print line,
# reached EOF, nothing more to read
proc.communicate() # close `proc.stdout`, wait for child process to terminate
print "Exit status", proc.returncode
To kill a subprocess, you could use its .kill() method e.g.:
from threading import Timer
def kill(process):
try:
process.kill()
process.wait() # to avoid zombies
except OSError: # ignore errors
pass
Timer(5, kill, [proc]).start() # kill in 5 seconds
thank you very much..but the problem is hcitool lescan never stops,and hence hangs out in the very next line of your code.,
and i found similar solution here it is.this works fine and i dont have to kill subprocess,this code takes some extra time to pour output,but this following code works preciesly,
from os import kill
import signal
import subprocess
import threading
import tempfile
import sys
import time
from tempfile import TemporaryFile
import commands
t = TemporaryFile()
global pipe_output
print commands.getoutput("hcitool dev")
print 'down'
commands.getoutput('hciconfig hci0 down')
print 'up'
commands.getoutput('hciconfig hci0 up')
print commands.getoutput("hcitool dev")
commands.getoutput('killall hcitool')
p = subprocess.Popen('hcitool lescan', bufsize = 0,shell = True, stdout =subprocess.PIPE,stderr = subprocess.STDOUT)
time.sleep(10)
#os.kill(p.pid,signal.SIGTERM)
for i in range(0,30,1):
print 'for'
inchar = p.stdout.readline()
i+=1
if inchar:
print 'loop num:',i
print str(inchar)
t.write(str(inchar))
print 'out of loop'
t.seek(0)
print t.read()
any help how to reduce waiting time,other than just changing time.sleep() ,is appreciated
thank you all
Use Popen class instead of the call class. hcitool lescan will run forever. subprocess.call waits for the call to be finished to return. Popen does not wait.