Python read and write to files error - python

I'm trying to write a python function that will take different strings and put them into a file such that it will become a python file. It will then run this python file using another python instance. I want this process to time out after a specified amount of time - for example in the case of an infinite loop. Here's the code:
# runTimeout.py
input_value = "x = addTwo(1,2)\n"
expected_output = "x == 3"
solution = "def addTwo(a, b):\n\treturn a+b"
timeout = 0.1
# Create the test file by adding (1)submission.solution (2)input_value (3)if (4)expected_output (5): (6) return True (6) return False
inputFile = solution + "\n" + input_value + "\n" + "if " + expected_output + ":" + "\n" + "\t" + "print True" + "\n" + "print False"
fin = open('inputfile', 'w')
fin.write(inputFile)
fin.close()
command = "python ~/Dropbox/django/inputFile > ~/Dropbox/django/outputFile"
def runTimeout(command, timeout):
import os, signal, time, commands
cpid = os.fork()
if cpid == 0:
while True:
commands.getstatusoutput(command)#[1].split('\n')
else:
time.sleep(timeout)
os.kill(cpid, signal.SIGKILL)
return
runTimeout(command, timeout)
fout = open('outputFile', 'r')
for line in fout:
print line
fout.close()
It correctly generates this inputFile:
def addTwo(a, b):
return a+b
x = addTwo(1,2)
if x == 3:
print True
print False
and this outputFile
True
False
but when I execute the code with python runTimeout.py, nothing is printed to the console. However, when I read out the file with the last four lines of runTimeout.py using the interpreter, I get the contents of outputFile. What's going on? I can't figure out why the same code works at once place, but not at the other.
I intend to put this into a django function after I get it working independently.
-- Update --
Brandon's solution helped, but for some reason, it doesn't seem to work consistently from the terminal - sometime, it prints True, sometime it prints nothing.
I wrote this new code instead, which works when it is a separate python file. Inside a Django function It fails (500 internal server error) on signal.signal(signal.SIGALRM, signal_handler)
command = "python ~/Dropbox/django/testcode/inputFile > ~/Dropbox/django/testcode/outputFile"
import signal, subprocess
def signal_handler(signum, frame):
raise Exception("Timed out!")
signal.signal(signal.SIGALRM, signal_handler) #fails here
signal.alarm(timeout)
results = ""
try:
subprocess.call(command, shell=True)
fout = open('outputFile', 'r')
for line in fout:
print line
results += line
fout.close()
except Exception:
print "Failure."
signal.alarm(0)
print "results = " + str(results)

I think you should wait until your child process exit which makes your code should look like this
def runTimeout(command, timeout):
import os, signal, time, subprocess
cpid = os.fork()
if cpid == 0:
while True:
subprocess.call(command, shell=True)
os._exit(0)
else:
time.sleep(timeout)
os.kill(cpid, signal.SIGKILL)
os.waitpid(cpid, 0)
return

Related

Python Checking If Multiple Programs are running and then upping a value written to a file

First of all I'm quite new to programming so sorry for the badly formatted/dodgy code
I am trying to make a program that tracks the amount of time certain programs is running. It sees if a program is running and then adds 1 to a variable which is then written to a file. The problem is I cannot run multiple loops at once to check if those programs are running. This leads to my code only checking if the first one is running.
My question is, is it possible to make several infinite loops at once to see if a program is running all at once. If so how do I do this. If there is another alternate solution that can accomplish the same thing please let me know down below.
I didnt know how to check if a program is running so i took the code used from here
The code I have right now is:
import time
import psutil
def programrunning(processName):
'''
Check if there is any running process that contains the given name processName.
'''
# Iterate over the all the running process
for proc in psutil.process_iter():
try:
# Check if process name contains the given name string.
if processName.lower() in proc.name().lower():
return True
except (psutil.NoSuchProcess, psutil.AccessDenied, psutil.ZombieProcess):
pass
return False;
def write(file, var):
store_thing = open(file, "w+")
store_thing.write(var)
store_thing.close()
def create(filename):
open(filename, "x")
def read(filename):
read_p = open(filename, "r")
read_p.mode == "r"
content = read_p.read()
return content
def whilerun(program):
while programrunning(program) == True:
var = read(program + ".txt")
programvar = var
programvar = int(programvar) + int(1)
time.sleep(1)
write(program + ".txt", str(programvar))
while programrunning(program) == False:
var = read(program + ".txt")
programvar = var
programvar = int(programvar) + int(1)
time.sleep(1)
write(program + ".txt", str(programvar))
whilerun("program1")
whilerun("program2")
whilerun("program3")
I'd put a loop for your programs.
programs = ["program1", "program2", "program3"]
def whilerun(programs):
while True:
any_alive = False # flag for inf loop prevention
for program in programs:
if programrunning(program):
# -- do sth for program running --
any_alive = True
else:
# -- do sth for program NOT running
pass
if not any_alive: # stop the loop if all processes are dead
break

How do I end the program once the last line of the text is reached?

I've written this code with the aim of exiting the code once the last line is reached and I've tried using the commented code but it only prints every alternating line.
try:
a = sys.argv[1]
with open(a, 'r') as f:
print(f.readline().strip('\n'))
while True:
x = input()
if x == '':
print(f.readline().strip('\n'))
# if not f.readline():
# exit()
continue
if x == 'q':
exit()
except OSError:
print("Error: Cannot open specified file.")
exit()
except IndexError:
print('Usage: python3 less.py <filename>')
exit()
TL;DR
while True:
x = input()
if x == '':
line = f.readline()
print(line.strip('\n'))
if line == '':
exit()
continue
if x == 'q':
exit()
The readline() method in Python will always read the next line, so when you call it multiple times, it will continually read another line. Since for every iteration of your while loop, you call the function twice, you are effectively ignoring the first line and checking the second line. By saving the output of f.readline() to a variable, you are not calling the function more than once per turn, and therefore will not skip any lines. Check out here for more information on Python file operations.
Yup, cpchristensen is right. I'd like to add that I believe there's a StopIteration exception that would execute once it reaches EOF. So, you could do something like this to exit the script once the exception triggers:
with open(sys.argv[1]) as lines:
try:
while True:
cur_line = next(lines)
# ... do something with current line
except StopIteration:
exit()

Issue processing data read from serial port, when displaying it in a Tkinter textbox

So i am reading (and displaying with a tkinter textbox) data from a serial connection, but i can't process the returning data as i would like to, in order to run my tests. In more simple terms, even though the machine response = 0x1 is displayed, i can't read it from the global serBuffer.
Before displaying it to the textbox i would read from inside the test function and then check if the response was in the string, but now that i pass the read data(strings) to a global variable and then try to read it, it doesn't seem to work, UNLESS i remove the serBuffer = "" from readserial. That results in a new issue though. When i press the button to send the command it sends it, but only receives the response after the second time i press it, and every time after. So as a result i get a Fail if i run the test once, but i get a pass everytime after.
Picture with the desired response ( that the test function doesn't read 0x1 and always returns FAIL)
Picture with the non-desired response ( that only receives the response after the second time a press it, and every time after. So as a result i get a Fail if i run the test once, but i get a pass every time after).
import tkinter as tk
import serial
from serial import *
serialPort = "COM3"
baudRate = 115200
ser = Serial(serialPort, baudRate, timeout=0, writeTimeout=0) #ensure non-blocking
#make a TkInter Window
mainWindow = tk.Tk()
mainWindow.wm_title("Reading Serial")
mainWindow.geometry('1650x1000+500+100')
scrollbar = tk.Scrollbar(mainWindow)
scrollbar.pack(side=tk.RIGHT, fill=tk.Y)
log = tk.Text ( mainWindow, width=60, height=60, takefocus=0)
log.pack()
log.config(yscrollcommand=scrollbar.set)
scrollbar.config(command=log.yview)
#make our own buffer
#useful for parsing commands
#Serial.readline seems unreliable at times too
serBuffer = ""
ser.write(b'\r\n')
def readSerial():
while True:
c = (ser.read().decode('utf-8', 'ignore')) # attempt to read a character from Serial
# was anything read?
if len(c) == 0:
break
# get the buffer from outside of this function
global serBuffer
# check if character is a delimeter
if c == '\r':
serBuffer += "\n" # don't want returns. chuck it
if c == '\n':
serBuffer += "\n" # add the newline to the buffer
# add the line to the TOP of the log
log.insert('1.1', serBuffer)
serBuffer = "" # empty the buffer
else:
serBuffer += c # add to the buffer
mainWindow.after(100, readSerial) # check serial again soon
def test():
command = b" test command \r\n"
ser.write(command)
global serBuffer
time.sleep(0.5)
if "0x1" in serBuffer:
print('PASS')
return 'PASS'
else:
print('FAIL')
return 'FAIL'
button = tk.Button(mainWindow, text="Pone Test", font=40, bg='#b1c62d', command=test)
button.place(relx=0.8, rely=0, relwidth=0.1, relheight=0.05)
# after initializing serial, an arduino may need a bit of time to reset
mainWindow.after(100, readSerial)
mainWindow.mainloop()
Comment: but only receives the response after the second time a press it, and every time after. So as a result i get a Fail if i run the test once, but i get a pass everytime after
Raise the first, timeout from 100 to 500 ore more.
# after initializing serial, an arduino may need a bit of time to reset
mainWindow.after(100, self.readSerial)
To find out the delay for the first response, try the following:
Note: You have to do this without running def readSerial, to prevent concurent empty the in buffer"
command = b" test command \r\n"
self.ser.write(command)
delay = 0.0
# wait until you get `.in_waiting` data.
while not self.ser.in_waiting:
time.sleep(0.1)
delay += 0.1
print('.', end='')
if delay >= 10:
print('BREAK after {} no in_waiting'.format(int(delay * 10)))
break
print('Delay:{}, in_waiting:{}'.format(delay, self.ser.in_waiting))
The following works for me.
Note: I use OOP syntax.
last_command
serBuffer = ""
last_command = None
Copy the ready read_buffer to last_command, empty only read_buffer
def readSerial(self):
while True:
c = (self.ser.read().decode('utf-8', 'ignore')) # attempt to read a character from Serial
# was anything read?
if len(c) == 0:
break
# get the buffer from outside of this function
global serBuffer
# check if character is a delimeter
if c == '\r':
serBuffer += "\n" # don't want returns. chuck it
if c == '\n':
serBuffer += "\n" # add the newline to the buffer
global last_command
last_command = serBuffer
# add the line to the TOP of the log
# log.insert('1.1', last_command)
print('readSerial.last_command:"{}"'.format(bytes(last_command, 'utf-8')))
serBuffer = "" # empty the buffer
else:
serBuffer += c # add to the buffer
print('readSerial:"{}"'.format(bytes(serBuffer, 'utf-8')))
self.after(100, self.readSerial) # check serial again soon
Do test()
def test(self, write=True):
print('test(write={})'.format(write))
if write:
command = b" test command \r\n"
self.ser.write(command)
self.after(500, self.test, False)
elif last_command is not None:
print('last_command:{}'.format(bytes(last_command, 'utf-8')))
if "0x1" in last_command:
print('PASS')
else:
print('FAIL')
else:
# ATTENTION: This could lead to a infinit loop
# self.after(500, self.test, False)
pass
Output:
test(write=True)
readSerial:"b' '"
readSerial:"b' t'"
readSerial:"b' te'"
readSerial:"b' tes'"
readSerial:"b' test'"
readSerial:"b' test '"
readSerial:"b' test c'"
readSerial:"b' test co'"
readSerial:"b' test com'"
readSerial:"b' test comm'"
readSerial:"b' test comma'"
readSerial:"b' test comman'"
readSerial:"b' test command'"
readSerial:"b' test command '"
readSerial:"b' test command \n\r'"
readSerial.last_command:"b' test command \n\r\n'"
test(write=False)
last_command:b' test command \n\r\n'
FAIL
Note: I get FAIL, because there is no 0x1 in last_command as i use PORT = 'loop://' which echo what is writen!
I made some changes, check this one.
def readSerial():
while True:
c = (ser.read(1).decode('utf-8', 'ignore')) from Serial
if len(c) == 0:
break
global serBuffer
if c == '\r':
serBuffer += ""
if c == '\n':
serBuffer += "\n"
log.insert(tk.END, serBuffer)
log.see(tk.END)
log.update_idletasks()
serBuffer = ""
else:
serBuffer += c
mainWindow.after(500, readSerial)

Run a command inside a running python script

I think it's a very easy thing to do but im still searching for an answer.
I have a Python script running which looks like this:
Waiting for argument:_________
Is there an easy way how i can start the script and automatically put some arguments in it?
I really don't understand u but i think u want something like
import os, sys
#def some_other_functions
def cmd():
try:
com = raw_input('Waiting for argument:_________ ')
#Or u can pass values as sys.args
#like com = sys.argv[1]
while len(com) == 0:
com = raw_input('Waiting for argument:_________ ')
if len(com) != 0:
print os.system(com)
if str(com) == 'exit':
sys.exit()
print '\nContinuer executing other commands or write --exit to quite the program\n'
while True:
com = raw_input('Waiting for argument:_________ ')
if len(com) == 0:
print 'Entered nothing'
if str(com) == 'exit':
sys.exit()
else:
print os.system(com)
except Exception, e:
print str(e)
cmd()

Get process name by PID

This should be simple, but I'm just not seeing it.
If I have a process ID, how can I use that to grab info about the process such as the process name.
Under Linux, you can read proc filesystem. File /proc/<pid>/cmdline contains the commandline.
Try PSUtil -> https://github.com/giampaolo/psutil
Works fine on Windows and Unix, I recall.
For Windows
A Way to get all the pids of programs on your computer without downloading any modules:
import os
pids = []
a = os.popen("tasklist").readlines()
for x in a:
try:
pids.append(int(x[29:34]))
except:
pass
for each in pids:
print(each)
If you just wanted one program or all programs with the same name and you wanted to kill the process or something:
import os, sys, win32api
tasklistrl = os.popen("tasklist").readlines()
tasklistr = os.popen("tasklist").read()
print(tasklistr)
def kill(process):
process_exists_forsure = False
gotpid = False
for examine in tasklistrl:
if process == examine[0:len(process)]:
process_exists_forsure = True
if process_exists_forsure:
print("That process exists.")
else:
print("That process does not exist.")
raw_input()
sys.exit()
for getpid in tasklistrl:
if process == getpid[0:len(process)]:
pid = int(getpid[29:34])
gotpid = True
try:
handle = win32api.OpenProcess(1, False, pid)
win32api.TerminateProcess(handle, 0)
win32api.CloseHandle(handle)
print("Successfully killed process %s on pid %d." % (getpid[0:len(prompt)], pid))
except win32api.error as err:
print(err)
raw_input()
sys.exit()
if not gotpid:
print("Could not get process pid.")
raw_input()
sys.exit()
raw_input()
sys.exit()
prompt = raw_input("Which process would you like to kill? ")
kill(prompt)
That was just a paste of my process kill program I could make it a whole lot better but it is okay.
Using psutil, here is the simplest code i can give you:
import psutil
# The PID ID of the process needed
pid_id = 1216
# Informations of the Process with the PID ID
process_pid = psutil.Process(pid_id)
print(process_pid)
# Gives You PID ID, name and started date
# psutil.Process(pid=1216, name='ATKOSD2.exe', started='21:38:05')
# Name of the process
process_name = process_pid.name()
Try this
def filter_non_printable(str):
ret=""
for c in str:
if ord(c) > 31 or ord(c) == 9:
ret += c
else:
ret += " "
return ret
#
# Get /proc/<cpu>/cmdline information
#
def pid_name(self, pid):
try:
with open(os.path.join('/proc/', pid, 'cmdline'), 'r') as pidfile:
return filter_non_printable(pidfile.readline())
except Exception:
pass
return

Categories