Taking the results of a bash command and using it in python - python

I am trying to write a code in python that will take some information from top and put it into a file.
I want to just write the name of the application and generate the file. The problem i am having is that i can't get the output of the pidof command so i can use it in python. My code looks like this :
import os
a = input('Name of the application')
val=os.system('pidof ' + str(a))
os.system('top -d 30 | grep' + str(val) + '> test.txt')
os.system('awk '{print $10, $11}' test.txt > test2.txt')
The problem is that val always has 0 but the command is returning the pid i want. Any input would be great.

First up, the use of input() is discouraged as it expects the user to type in valid Python expressions. Use raw_input() instead:
app = raw_input('Name of the application: ')
Next up, the return value from system('pidof') isn't the PID, it's the exit code from the pidof command, i.e. zero on success, non-zero on failure. You want to capture the output of pidof.
import subprocess
# Python 2.7 only
pid = int(subprocess.check_output(['pidof', app]))
# Python 2.4+
pid = int(subprocess.Popen(['pidof', app], stdout=subprocess.PIPE).communicate()[0])
# Older (deprecated)
pid = int(os.popen('pidof ' + app).read())
The next line is missing a space after the grep and would have resulted in a command like grep1234. Using the string formatting operator % will make this a little easier to spot:
os.system('top -d 30 | grep %d > test.txt' % (pid))
The third line is badly quoted and should have caused a syntax error. Watch out for the single quotes inside of single quotes.
os.system("awk '{print $10, $11}' test.txt > test2.txt")

Instead of os.system, I recommend you to use the subprocess module: http://docs.python.org/library/subprocess.html#module-subprocess
With that module, you can communicate (input and output) with a shell. The documentation explains the details of how to use it.
Hope this helps!

Related

Test for a program that receives input from keyboard

I have done a program that receives input from the terminal with the readline function in c (https://eli.thegreenplace.net/2016/basics-of-using-the-readline-library/), readline saves keyboard input from the terminal (basically a read for the stdin) and saves it inside a buffer.
Imagine, when my program is executed, it just prints a message on the screen like: *Enter a command: * and I can write a bash command and it's going to execute it (Just like bash).
I wanted to do a test (In python, c++ or bash) that is going to start the program, and writes into the readline and check is output compared to bash, does anyone knows a way to do it?
Here is an initial bash script that randomizes input with some properties:
for i in {1..5}; do
input=$(echo {A..Z} {a..z} | tr ' ' "\n" | shuf | xargs | tr -d ' ' | cut -b 1-18)
echo ${input}
/path/to/your_program < ${input}
done
You can add characters, make the input shorter etc.
I think what you want is to grab the input in python (I suggest you use the input() function), store it in a variable, then print it out in the terminal using print()

How do i make my awk command into a python command

I have an awk command that works in bash, but im now trying to put it into a python script
I have tried both os.system, and subprocess.call both return the same error. sh: 1: Syntax error: "(" unexpected
os.system('awk \'FNR<=27{print;next} ++count%10==0{print;count}\' \'{0} > {1}\'.format(inputfile, outpufile)')
So this awk command will take the large inputfile and create an output file that leaves the first 27 lines of header, but then starting on line 28 it only takes every 10th line and puts it into the output file
Im using the .format() because it is within a python script where the input file will be different every times its run.
ive also tried
subprocess.call('awk \'FNR<=27{print;next} ++count%10==0{print;count}\' \'{0} > {1}\'.format(inputfile, outpufile)')
both come up with the same error above. What am I missing?
As per the comment above, probably more pythonic (and more manageable) to directly use python.
But, if you want to use awk then one way is to format your command with your variable filenames separately.
This works using a basic test text file:
import os
def awk_runner(inputfile, outputfile):
cmd = "awk 'FNR<=27{print;next} ++count%10==0{print;count}' " + inputfile + " > " + outputfile
os.system(cmd)
awk_runner('test1.txt', 'testout1.txt')
There are two main issues with your Python code:
format() is a python method call, it should not be put into the string of awk_cmd to execute under the shell
when calling format() method, braces {} are used to identify substitution target in the format string objects, they need to be escaped using {{ ... }}
See below a modified version of your code:
awk_cmd = "awk 'FNR<=7{{print;next}} ++count%10==0{{print;count}}' {0} > {1}".format(inputfile, outpufile)
os.system(awk_cmd)

How to fix "awk: Syntax error Context is: >>> ' -'' <<<" error in python subprocess?

Trying to do p4 files with subprocess.Popen and then pass that output to awk again via subprocess.Popen. Input will be of the form:
//xxx/xx/xx/xx/xx/xx.xx#99 - edit change xxxxxxx (text+k)
Replaced original names with 'x'es here since it's all proprietary information. Would like to split based on the " -"(space hyphen) and get the file name with revision number.
awk_cmd = ["awk","-F\' -\'","\'{print $1}\'"]
awk_cmd_output = subprocess.Popen(awk_cmd, stdout=subprocess.PIPE, stdin = p4_files_output.stdout)
Seeing this error coming from awk:
awk: Syntax error Context is:
' -'' <<<
When I run the same in cmd awk -F' -' '{print $1}', it works fine. It seems like awk is getting an extra single quote in the end. It should ideally be ' -' and not ' -''.
sticking to awk & subprocess solution, just use double quotes and drop the single quotes, that are only useful for the shell, but passed literally to the process when using subprocess, which make the command fail:
awk_cmd = ["awk","-F -","{print $1}"]
Let subprocess add the proper quoting. It won't split the arguments according to spaces.
But the best way would be to drop awk, and use str.split, something like:
output = []
for line in p4_files_output.stdout:
output.append(line.decode().split(" -")[0])
output_text = "\n".join(output)
or single line using a comprehension:
output_text = "\n".join([line.decode().split(" -")[0] line in p4_files_output.stdout])

Python using grep from os.system adds "0" line to variable?

I'm running grep from within a python script like so:
last_run_start = os.system("cat %(file)s | grep '[0-24]:[0-59]' | tail -n1" % locals())
Which pulls out the last timestamp in file. When I do this through the Python command line, or use that grep command through regular terminal, I get what would be expected - the last line containing a timestamp.
However, when run from this script last_run_start is returning this:
18:23:45
0
Whats causing this '0' to appear, let alone on a new line? More importantly, how can I remove it from last_run_start?
os.system returns the exit code of the command you've run, which in this case seems to be 0.
The output of the command goes directly to stdout and isn't stored in last_run_start, if you want that you should use Popen or check_output from the subprocess module.
I guess the 0 ends up being printed because you're printing last_run_start somwhere.

Escaping escape sequence in Python

I am kind of new to python. Goal is to execute a shell command using subprocess parse & retrive the printed output from shell. The execution errors out as shown in the sample output msg below. Also shown below is the sample code snippet
Code snippet:
testStr = "cat tst.txt | grep Location | sed -e '/.*Location: //g' "
print "testStr = "+testStr
testStrOut = subprocess.Popen([testStr],shell=True,stdout=subprocess.PIPE).communicate()[0]
Output:
testStr = cat tst.txt | grep Location | sed -e '/.*Location: //g'
cat: tst.txt: No such file or directory
sed: -e expression #1, char 15: unknown command: `/'
Is there a workaround or a function that could be used ?
Appreciate your help
Thanks
I suppose your main error is not python related. To be more precise, there are 3 of them:
You forgot to import subprocess.
It should be sed -e 's/.*Location: //g'. You wrote ///g instead of s///g.
tst.txt does not exist.
You should be passing testStr directly as the first argument, rather than enclosing it in a list. See subprocess.Popen, the paragraph that starts "On Unix, with shell=True: ...".

Categories

Resources