Calling an external program from python - python

So I have this shell script:
echo "Enter text to be classified, hit return to run classification."
read text
if [ `echo "$text" | sed -r 's/ +/ /g' | bin/stupidfilter data/c_rbf` = "1.000000" ]
then
echo "Text is not likely to be stupid."
fi
if [ `echo "$text" | sed -r 's/ +/ /g' | bin/stupidfilter data/c_rbf` = "0.000000" ]
then
echo "Text is likely to be stupid."
fi
I would like to write it in python. How do I do this?
(As you can see it uses the library http://stupidfilter.org/stupidfilter-0.2-1.tar.gz)

To do it just like the shell script does:
import subprocess
text = raw_input("Enter text to be classified: ")
p1 = subprocess.Popen('bin/stupidfilter', 'data/c_trbf')
stupid = float(p1.communicate(text)[0])
if stupid:
print "Text is likely to be stupid"
else:
print "Text is not likely to be stupid"

You could clearly run the commands as sub-shells and read the return value, just as in the shell script, and then process the result in Python.
This is simpler than loading C functions.
If you really want to load a function from the stupidfilter library, then first look to see whether someone else has already done it. If you cannot find anyone who has, then read the manual - how to call from Python onto C is covered in there.
It is still simpler to use what others have already done.

Related

Python colored output doesn't work except when piping

I'm using Git Bash on Windows inside Windows Terminal and I'm writing a python script which needs to output colored text. As an example, I have the following one-line script named example.py:
print('\033[35m\033[K' + 'hello world' + '\033[m\033[K')
When I run the command python example.py, I expect to see colored output, but instead I get this:
←[35m←[Khello world←[m←[K
However, if I run python example.py | cat, I get the colored output I expect. How weird. I also get nice colored output if I run the script from cmd instead of bash, or if I run the line from the live interpreter (but not if it is a child of bash).
Any ideas? If possible I prefer to solve this without bringing in dependencies like Colorama.
EDIT: I resigned to using Colorama after seeing the replies. All it took to fix it was a call to the aptly named colorama.just_fix_windows_console(). Dependency-less solutions still welcome.
EDIT 2: Interestingly, this problem does not occur on my laptop which has what I thought was the exact same setup.
For the record, I tried the following basic script,
#!/usr/bin/python3.8
print('\033[35m\033[K' + 'hello world' + '\033[m\033[K')
and I got the result which you were likely looking for, namely
Since you mentioned bash, to get what you wanted, you need to read the section of the bash man page for printf more closely.
The round brackets are used in AWK, C, others. Bash shows no mention of round brackets in the usage syntax. However, you need to add a "format" specifier (NOT same as AWK), but per the man page.
Your statement should be reworked to show as this:
printf "%b\n" "\033[35m\033[K" "hello world" "\033[m\033[K"
OR ... you could just replace the printf "%b\n" with simply echo -e to get the same result.
Of possible interest, I also created for myself what I call a "Bourne Header" file, in which I defined some preset combinations with variable strings that can be re-used in other scripts by simply source'ing the *.bh file. I include it here for general usage.
#!/bin/sh
##########################################################################################################
### $Id: INCLUDES__TerminalEscape_SGR.bh,v 1.2 2022/09/03 01:57:31 root Exp root $
###
### This includes string variables defined to perform various substitutions for the ANSI Terminal Escape Sequences, i.e. SGR (Select Graphic Rendition subset)
##########################################################################################################
### REFERENCE: https://en.wikipedia.org/wiki/ANSI_escape_code
### https://www.ecma-international.org/publications-and-standards/standards/ecma-48/
### "\e" is same as "\033"
style_e()
{
boldON="\e[1m"
boldOFF="\e[0m"
italicON="\e[3m"
italicOFF="\e[0m"
underlineON="\e[4m"
underlineOFF="\e[0m"
blinkON="\e[5m"
blinkOFF="\e[0m"
cyanON="\e[96;1m"
cyanOFF="\e[0m"
cyanDarkON="\e[36;1m"
cyanDarkOFF="\e[0m"
greenON="\e[92;1m"
greenOFF="\e[0m"
yellowON="\e[93;1m"
yellowOFF="\e[0m"
redON="\e[91;1m"
redOFF="\e[0m"
orangeON="\e[33;1m"
orangeOFF="\e[0m"
blueON="\e[94;1m"
blueOFF="\e[0m"
blueSteelON="\e[34;1m"
blueSteelOFF="\e[0m"
darkBlueON="\e[38;2;95;95;255m"
darkBlueOFF="\e[0m"
magentaON="\e[95;1m"
magentaOFF="\e[0m"
}
style_o()
{
boldON="\033[1m"
boldOFF="\033[0m"
italicON="\033[3m"
italicOFF="\033[0m"
underlineON="\033[4m"
underlineOFF="\033[0m"
blinkON="\033[5m"
blinkOFF="\033[0m"
cyanON="\033[96;1m"
cyanOFF="\033[0m"
cyanDarkON="\033[36;1m"
cyanDarkOFF="\033[0m"
greenON="\033[92;1m"
greenOFF="\033[0m"
yellowON="\033[93;1m"
yellowOFF="\033[0m"
redON="\033[91;1m"
redOFF="\033[0m"
orangeON="\033[33;1m"
orangeOFF="\033[0m"
blueON="\033[94;1m"
blueOFF="\033[0m"
blueSteelON="\033[34;1m"
blueSteelOFF="\033[0m"
darkBlueON="\033[38;2;95;95;255m"
darkBlueOFF="\033[0m"
magentaON="\033[95;1m"
magentaOFF="\033[0m"
}
#style_e
style_o
##########################################################################################################
### Usage Examples:
##########################################################################################################
# echo "\t RSYNC process is ${redON}not${redOFF} running (or has already ${greenON}terminated${greenOFF}).\n"
# echo "\t ${PID} is ${cyanON}${italicON}${descr}${italicOFF}${cyanOFF} process ..."
# echo "\t ${PID} is ${yellowON}${descr}${yellowOFF} process ..."
# echo "\n\n\t RSYNC process (# ${pid}) has ${greenON}completed${greenOFF}.\n"
##########################################################################################################
### Example of scenario where escape codes are hard-coded; \e was not accepted by awk
##########################################################################################################
# echo "\n\t ${testor}\n" | sed 's+--+\n\t\t\t\t\t\t\t\t--+g' | awk '{
# rLOC=index($0,"rsync") ;
# if( rLOC != 0 ){
# sBeg=sprintf("%s", substr($0,1,rLOC-1) ) ;
# sEnd=sprintf("%s", substr($0,rLOC+5) ) ;
# sMid="\033[91;1mrsync\033[0m" ;
# printf("%s%s%s\n", sBeg, sMid, sEnd) ;
# }else{
# print $0 ;
# } ;
# }'
##########################################################################################################
echo "\n\t Imported LIBRARY: INCLUDES__TerminalEscape_SGR.bh ..."
##########################################################################################################
You could likewise define your own set of preset escape sequences as formatting variables.

Getting user input for os.system

Only recently started to learn Python, so please excuse the noob question (might be doing this completely wrong to begin with)
I'm trying to get user input to use with os.system
import os
account = input("Account name: ")
os.system("op get item + account + | awk -F':' '{print $24}' | cut -d '}' -f 1")
this line of code is used to take and display the information from 1Password and outputs just
the password of Facebook is this example, it works but as soon as i try to add the variable it breaks
op get item Facebook | awk -F':' '{print $24}' | cut -d '}' -f 1
I hope someone here can help me out or point me in the right direction, thanks!
I think that you need to work with the output of these commands, so you can use the subprocess module instead: Replacing Shell Pipeline
For example:
from subprocess import check_output
check_output(f"op get item {account} | awk -F':' '{{print $24}}' | cut -d '}}' -f 1", shell=True)
Be aware that you would like to sanitize the account variable, before touching your system calls. :)
You just need string substitution, e.g. with Python3.6+ the elegant
os.system(f"op get item {account} | awk -F':'" + " '{print $24}' | cut -d '}' -f 1")

Send parameters to python from bash

I have a bash script that calls a python script with parameters.
In the bash script, I'm reading a file that contains one row of parameters separated by ", and then calls the python script with the line I read.
My problem is that the python gets the parameters separated by the space.
The line looks like this: "param_a" "Param B" "Param C"
Code Example:
Bash Script:
LINE=`cat $tmp_file`
id=`python /full_path/script.py $LINE`
Python Script:
print sys.argv[1]
print sys.argv[2]
print sys.argv[3]
Received output:
"param_a"
"Param
B"
Wanted output:
param_a
Param B
Param C
How can I send the parameters to the Python script the way I need?
Thanks!
What about
id=`python /full_path/script.py $tmp_file`
and
import sys
for line in open(sys.argv[1]):
print(line)
?
The issue is in how bash passes the arguments. Python has nothing do to with it.
So, you have to solve all these stuff before sending it to Python, I decided to use awk and xargs for this. (but xargs is the actual MVP here.)
LINE=$(cat $tmp_file)
awk -v ORS="\0" -v FPAT='"[^"]+"' '{for (i=1;i<=NF;i++){print substr($i,2,length($i)-2)}}' <<<$LINE |
xargs -0 python ./script.py
First $(..) is preferred over backticks, because it is more readable. You are making a variable after all.
awk only reads from stdin or a file, but you can force it to read from a variable with the <<<, also called "here string".
With awk I loop over all fields (as defined by the regex in the FPAT variable), and print them without the "".
The output record separator I choose is the NULL character (-v ORF='\0'), xargs will split on this character.
xargs will now parse the piped input by separating the arguments on NULL characters (set with -0) and execute the command given with the parsed arguments.
Note, while awk is found on most UNIX systems, I make use of FPAT which is a GNU awk extension and you might not be having GNU awk as default (for example Ubuntu), but gnu awk is usually just a install gawk away.
Also, the next command would be a quick and easy solution, but generally considered as unsafe, since eval will execute everything it receives.
eval "python ./script "$LINE
This can be done using bash arrays:
tmp_file='gash.txt'
# Set IFS to " which splits on double quotes and removes them
# Using read is preferable to using the external program cat
# read -a reads into the array called "line"
# UPPERCASE variable names are discouraged because of collisions with bash variables
IFS=\" read -ra line < "$tmp_file"
# That leaves blank and space elements in "line",
# we create a new array called "params" without those elements
declare -a params
for((i=0; i < ${#line[#]}; i++))
do
p="${line[i]}"
if [[ -n "$p" && "$p" != " " ]]
then
params+=("$p")
fi
done
# `backticks` are frowned upon because of poor readability
# I've called the python script "gash.py"
id=$(python ./gash.py "${params[#]}")
echo "$id"
gash.py:
import sys
print "1",sys.argv[1]
print "2",sys.argv[2]
print "3",sys.argv[3]
Gives:
1 param_a
2 Param B
3 Param C

How do I find the result of a find, in this script for sending by email

How do I find the result of a find, in this script for sending by email ??
I've tried this way
How do I put the result within the email.
The result of find
mailx -s "result of find " support#systems.com
You need to "pipe" it.
find /bin | mailx -s "result of find in /bin" support#systems.com
Pipes allow you to transfer the output of a shell command into input of another command. They are very convenient and widely use in the linux/unix systems.
You should look into it.
Something like this would meet your needs:
find /path_to_examine -type f -print | mailx -s "Find Results" support#systems.com
mailx expects its input from STDIN; either read from the initiating terminal (and terminated with a control-D sequence); or redirected; or piped. The example chosen uses a pipe. You could also redirect an already created file, thusly:
mailx -s "Find Results" support#systems.com < myresults

Sending piped commands with pxssh/pexpect

I am currently working with pxssh for Python and it's working like a charm, however it seems like it doesn't process piped (|) commands - it interprets them as separate ones.
At the moment I have the following:
s = pxssh.pxssh()
s.login(sshHost, sshUsername, sshPassword)
s.sendline("cat somefile | grep something | cut -d \' -f 4")
It works properly with any commands that are not piped, however I need to send a piped one at the moment.
Is there a way around this with pxssh, or can you please suggest a way to implement another solution for this command?
It's not clear to me why pxssh would behave as you describe. Are you sure the issue is not that your \' is interpreted by Python, whereas you want it to be interpreted by the remote shell? That would be better spelled like so:
s.sendline("cat somefile | grep something | cut -d \\' -f 4")
You certainly do have alternatives. One would be to use a single command instead of a pipeline, such as:
s.sendline("sed -n '/something/ { s/\\([^,]*,\\)\\{3\\}\\([^,]*\\),.*/\\2/; p }'")
As a special case of that, you could launch a subshell in which to run your pipeline:
s.sendline('''bash -c "cat somefile | grep something | cut -d \\' -f 4"''')

Categories