Running script file through subprocess - python

I'm attempting to run a Linux script through Python's subprocess module. Below is the subprocess command:
result = subprocess.run(['/dir/scripts/0_texts.sh'], shell=True)
print(result)
Here is the 0_texts.sh script file:
cd /dir/TXTs
pylanguagetool text_0.txt > comments_0.txt
The subprocess command executes the script file, writing a new comments_0.txt in the correct directory. However, there's an error in the execution. The comments_0.txt contains an error of "input file is required", and the subprocess result returns returncode=2. When I run the pylanguagetool text_0.txt > comments_0.txt directly in the terminal the command executes properly, with the comments_0.txt written with the proper input file of text_0.txt.
Any suggestions on what I'm missing?

There is some ambiguity here in that it's not obvious which shell is run each time 0_texts.sh is invoked, and whether it has the values you expect of environment variables like PATH, which could result in a different copy of pylanguagetool running from when you call it at the command line.
First I'd suggest removing the shell=True option in subprocess.run, which is only involving another, potentially different shell here. Next I would change subprocess.run(['/dir/scripts/0_texts.sh']) to subprocess.run(['bash', '/dir/scripts/0_texts.sh']) (or whichever shell you wanted to run, probably bash or dash) to remove that source of ambiguity. Finally, you can try using type pylanguagetool in the script, invoking pylanguagetool with its full path, or calling bash /dir/scripts/0_texts.sh from your terminal to debug the situation further.
A bigger-picture issue is, pyLanguageTool is a Python library, so you're almost certainly going to be better off calling its functions from your original Python script directly instead of using a shell script as an intermediary.

Related

Subprocess Popen to run python command

I need to run a python command inside a Popen. The problem is that the command NEEDS to run in python3 and I need it to be portable, which means that I can't really use the python3 alias for every situation...
I have computers where python is already the correct version, and others where the correct one is python3. I tried to insert #!/usr/bin python3 in the beginning of the file and then run as python but it didn't work.
I can't modify environment vars to change python3 to python. I would like to know if there is a way to check which one I need to use or a way to change the python3 to python ONLY inside the Popen command...
The Popen command I am trying to run is very simple and no I can't just import the file and use as a class... it needs to be ran through Popen. Also, virtualenv or similars are not an option.
subprocess.Popen(['python', 'main.py'], shell=True, universal_newlines=True)
The shebang -- the initial line showing which interpreter to use, such as #!/usr/bin/python or #!/usr/bin/python3 -- is only honored if you don't explicitly select an interpreter yourself: If you run python foo.py, the OS is invoking a specific Python interpreter and passing it foo.py as an argument (which it interprets as the name of a script it should run); whereas when you run ./foo.py, you're telling the OS itself to figure out which interpreter to use to run foo.py, which it does by looking at the shebang.
To leave it up to the operating system to select, just explicitly specify the name of your script:
subprocess.Popen(['./main.py'], universal_newlines=True)

passing the output of one .py script to another in GDB

How to pass the output of one .py script which I executed in GDB using below command:
(gdb)source myfilename.py
to another .py script myfilename2.py
E.g: On running myfile myfilename.py in GDB I get the below results
(gdb)source myfilename.py
(gdb)print $function("input")
(gdb)$1 = someoutput`
If I want to pass $1 as input to another .py script how do I do it.
Thanks for the help.
I'm not sure if you can run other python programs output to another in gdb, but of course you can pass output of a command like this.
(gdb) run "`python -c 'print "\xff\xff\xff\xff"'`"
May be you can try passing the second .py file instead of the command for its output to be passed into first .py.
You cannot use contents of GDB variable $1 for your program input, since program launch is performed by shell, not by gdb.
You can store your script output in file, launch gdb for your executable and use command
(gdb)run <outputfile
Or use a named pipe, as suggested in this answer.

Python: Subprocess "call" function can't find path

I have a python program that needs to run a bash command on a server. The program works when I run a bash command in my local directory like this:
import subprocess
from subprocess import call
call(['bash', 'Script_Test.sh'])
However, after SSH'ing to a server and running a similar line of code below with a path on the server to a bash script, I get the error "No such file or directory"
call['bash', path]
This doesn't make sense for a number of reasons. I triple checked that the path is correct. I went on Putty, connected to the server on there, and ran a bash command with the same path and it worked, so it can't be the path. I also ran a number of tests to make sure I was SSH'd into the correct server, and I was. I thought there was a security issue on the server with me running bash, so I tried cat instead. Nope, still unable to locate the path.
I'm not super familiar with python subprocesses, so any pointers to anything I'm missing here with "call" would be very helpful.
Making Sure Your Script is Ready for Execution
Give your script a shebang line
First things first, it is important that you include a shebang line in your script on Unix-like systems. I recommend, for your script's portability, that you use #!/usr/bin/env bash.
A Note on File Extensions:
I would recommend that you remove the .sh extension from your script. If you are using the Bourne Again Shell (bash) to execute your script, then using the .sh extension is misleading. Simply put, the Bourne Shell (sh) is different than the Bourne Again Shell (bash) - so don't use a file extension that suggests you are using a different shell than you actually are!
It's not the end of the world if you don't do change your file extension - your script will still be executed as a bash script if you have the proper bash shebang line. Still, it is good practice to either use no file extension (Script_Test -- strongly preferred) or the .bash file extension (Script_Test.bash).
Give your script the proper file permissions
For your purposes, maybe it is only important to give the current user permissions to read and execute the script. In that case, use chmod u+x Script_Test.sh. What is important here is that the correct user (u+) / group (g+) has permissions to execute the script.
Make sure that your script's path is in the $PATH environment variable
Executing your bash script in a Python script
Once you've followed these steps, your Python script should work as you've called it in your question:
import subprocess
from subprocess import call
your_call = call("Test_Script.sh")
If you would rather not move your script into the $PATH environment variable, just make sure that you refer to the script's full path (which is the current directory, ./, in your case):
import subprocess
from subprocess import call
your_call = call("./Test_Script.sh")
Lastly, if your script does not have a shebang line, you will need to specify an additional parameter in your call function:
import subprocess
from subprocess import call
your_call = call("./Test_Script.sh", shell=True)
However, I would not recommend this last approach. See the Python 2.7.12 documentation for the subprocess package...
Warning: Using shell=True can be a security hazard. See the warning under Frequently Used Arguments for details.
Please check out #zenpoy's explanation to a similar StackOverflow question if you are still having problems.
Happy coding!

Run a program in Python's subprocess module, with required files from Terminal

Is it feasible to run a program in Python's subprocess module, but with files from Terminal?
So I want to run the following program from within Python:
myProgram -a myArg
However, suppose that the above program requires the file myFile in the current directory, and it doesn't take the required file as an argument. So, if you run the above program in the directory where there is myFile, the program succeeds in processing. However, if you run it in the directory where there is NOT myFile, the execution fails.
And when I tried to execute the program from within Python's subprocess.Popen(), with shell=True, the program doesn't work and it looks like the reason it failed is the program wasn't able to read myFile when executed from within Python.
So, is there any way to run it successfully from within Python?
subprocess.Popen('myProgram -a myArg', cwd='/folder/with_myFile/')
Similar Question: Python specify popen working directory via argument

Shell script change shell in between

I've a shell script with two shebangs, the first one tells #!/bin/sh and after a few lines the other one is #!/usr/bin/env python.
When this script is given executable permission and ran as ./script.sh, the script works fine, uses /bin/sh in first part and uses python interpreter in latter part.
But when the script is run as sh script.sh, the second shebang is not recognized and the script fails. Is there anyway I can force to change the interpreter if the script is run explicitly as sh script.sh.
The reason I need this is because I need to run the scripts through a tool which runs as sh script.sh
As far as I know you cannot have two shebang lines in one script. The shebang works only when -
it is on the first line
it starts in column one
If you need to run python code then have it in another script and then call the script by doing
python path/to/the/script.py
A better way to do this would be to use a shell here document. Something like this:
#!/bin/sh
curdir=`pwd`
/usr/bin/env python <<EOF
import os
print os.listdir("$curdir")
EOF
This way, you won't need to distribute the code on two separate files.
As you see, you can even access shell variables from the python code.
have your script.sh script invoke the python interpreter directly:
#!/bin/sh
# include full path if needed
python (your python interpreter arguments)

Categories

Resources