Python subprocess communication - python

I'm trying to run a python script that will open a command prompt(OSGeo4W.bat is a command prompt line). I can get it to open but now I would like to send the command prompt commands.
import subprocess
myProcess = subprocess.Popen(['C:\OSGeo4W64\OSGeo4W.bat'],shell = False) #opens command prompt
myProcess.communicate('gdal2tiles -p raster -z 0-1 new.jpg abc')
myProcess.wait()
print("my process has terminated")
I've also tried
subprocess.check_call('gdal2tiles -p raster -z 0-1 new.jpg abc', shell=False)
I keep getting errors that say "WindowsError: [Error 2] The system cannot find the file specified"
although, if I were to keep the command prompt that it opens and type in " 'gdal2tiles -p raster -z 0-1 new.jpg abc' " then it will work just as I wanted. Help would be great, thanks!

Try:
check_call('gdal2tiles -p raster -z 0-1 new.jpg abc', shell=True)
shell=True changes how the executable is searched on Windows.
Or if gdal2tiles works only in the environment created by OSGeo4W.bat:
shell = Popen(r'C:\OSGeo4W64\OSGeo4W.bat', stdin=subprocess.PIPE)
shell.communicate('gdal2tiles -p raster -z 0-1 new.jpg abc')
# you don't need shell.wait() here
Notice: r"" literal. It is necessary to avoid escaping the backslashes in the path.

For those of you that are still trying to figure this one out, this is what I found. The "stdin=subprocess.PIPE" method above works with some command line tool in OSGeo4W64 but not all. It works with gdal_translate but not pdal translate for example. Not sure why;(
My Solution:
OSGeo4Wenv = r'CALL "C:/OSGeo4W64/bin/o4w_env.bat" '
pdal_translate_String = r'c:/OSGeo4W64/bin/pdal translate c:\inputFile c:\outputFile radiusoutlier --filters.radiusoutlier.min_neighbors=2 --filters.radiusoutlier.radius=8.0 --filters.radiusoutlier.extract=true'
Cmd = str(OSGeo4Wenv)+' & '+str(pdal_translateCmd)
shell = subprocess.call(Cmd, stdout=None, shell=True)
What is going on?
1) Open shell and set up the OSGeo4W environment by calling "OSGeo4Wenv". This is normally called by the OSGeo4W.bat file. Without this, the command line programs don't know where to look for the libraries.
2) The pdal_translate command is then sent to the dos shell because in Windows, multiple commands can be separated by the "&" symbol. I use the .call method of python 2.7. It has the advantage that it waits for the end of the process. That is nice if you use the multiprocessing map.pool method to launch multiple processes at the same time.
Hope this help others!
Nicolas

Related

execute command in gnome-terminal using python

I am trying to open one file from gnome-terminal using python. But I am not able to do it.It is just opening terminal and not opening file.
I have tried like:
import os
os.system('gnome-terminal --working-directory = "folder_path" + "[-e, --command=" kate aaa.txt""')
Can anyone please help?
The problem is + "[-e, --command=" kate aaa.txt"", gnome-terminal doesn't know how to parse this + "[ and "", according to the manual, -e and --command mean the same thing:
man gnome-terminal
...
--command, -e=COMMAND
Split the argument to this option into a program and arguments in the same way a shell
would, and execute the resulting command-line inside the terminal.
This option is deprecated. Instead, use -- to terminate the options, and put the program
and arguments to execute after it: for example, instead of gnome-terminal -e "python3 -q",
prefer to use gnome-terminal -- python3 -q.
Note that the COMMAND is not run via a shell: it is split into words and executed as a
program. If shell syntax is required, use the form gnome-terminal -- sh -c '...'.
This works for me in Archlinux:
import os
os.system('gnome-terminal --working-directory = /home/ramsay --command="kate
os"')

How to perform a cd command and execute additional command in a new terminal from a python script?

I am trying to run a python script on ubuntu18, which simply will open a new terminal/tab,navigate to a specific folder and then execute a command. But this simple task is looking very daunting due to my lack of knowledge.
Expected:
In the python script
$cd /home/metabase
$java -jar metabase.jar
My code:
try1:
cmd = "gnome-terminal --tab 'cd /home/metabase/java -jar metabase.jar; read'"
os.system(cmd)
New tab opens but nothing happens
try2:
subprocess.call(['cd /home/metabase/', 'java -jar metabase.jar'])
Error:No such file or directory
I tried many other combinations. But results in either new tab not opening or new tab opens but in the same directory and does nothing.
I did some reading on the problem. It seems like i am creating these subprocess and therefore when i do the CD, it does nothing. Anyways,i looked into many similar stackoverflow threads but i am still lost. Any direction would be appreciated. Thank you
The command to open a new gnome-terminal window with a bash command is:
gnome-terminal -- bash -c 'your command'
In your case:
gnome-terminal -- bash -c 'cd /home/metabase; java -jar metabase.jar; read'
Make sure this works from a shell first. Then you can invoke it from Python:
subprocess.call(["gnome-terminal", "--", "bash", "-c", "cd /home/metabase; java -jar metabase.jar; read"])
Why do you want to change the directory ? If you want you can do it directly :
os.system('java -jar /home/metabase/metabase.jar') which will return the process exit value , 0 means success.
Keep in mind that os.system will execute the command passed as a string in a sub-shell.
If you do not want to spawn a new shell, you can use:
subprocess.call(['java', '-jar', '/home/metabase/metabase.jar']) in this way there is no system shell started up, so the first argument must be a path to an executable file.

Sending CMD command prompts using Subprocess (Python)

This is a beginner level question for anyone pro in subprocess.
In Windows, is it possible for me to send the following CMD commands using subprocesssuch that they are executed one after another in a single shell:
cd C:\Users\User\myvirtualenvs\project1
Scripts\activate.bat
Hello.py
Effectively, I am trying to load the Virtualenv without having to manually myself touch CMD prompt.
Thanks in advance :)
Just like mentioned in the Comment with &&:
from subprocess import call
call(r'cd C:\ && echo 123 && dir', shell=True)
Please notice the shell=True argument.
Edit due to comment:
Shell=True is an security issue, if you're passing raw input values to the call. See this example from the docs:
from subprocess import call
filename = input("What file would you like to display?\n")
>>> What file would you like to display?
>>> non_existent; rm -rf / #
call("cat " + filename, shell=True) # Uh-oh. This will end badly...
In initially thought you want to make a small script for personal purposes. If you want to give this code away, think about packaging your code via distutils or setuptools.

Open new gnome-terminal and run command

I'm trying to write a script that opens a new terminal then runs a separate python script from that terminal.
I've tried:
os.system("gnome-terminal 'python f.py'")
and
p = Popen("/usr/bin/gnome-terminal", stdin=PIPE)
p.communicate("python f.py")
but both methods only open a new terminal and do not run f.py. How would I go about opening the terminal AND running a separate script?
Edit:
I would like to open a new terminal window because f.py is a simply server that is running serve_forever(). I'd like the original terminal window to stay "free" to run other commands.
Like most terminals, gnome terminal needs options to execute commands:
gnome-terminal [-e, --command=STRING] [-x, --execute]
You probably need to add -x option:
x, --execute
Execute the remainder of the command line inside the terminal.
so:
os.system("gnome-terminal -x python f.py")
That would not run your process in the background unless you add & to your command line BTW.
The communicate attempt would need a newline for your input but should work too, but complex processes like terminals don't "like" being redirected. It seems like using an interactive tool backwards.
And again, that would block until termination. What could work would be to use p.stdin.write("python f.py\n") to give control to the python script. But in that case it's unlikely to work.
So it seems that you don't even need python do to what you want. You just need to run
python f.py &
in a shell.
As of GNOME Terminal 3.24.2 Using VTE version 0.48.4 +GNUTLS -PCRE2
Option “-x” is deprecated and might be removed in a later version of gnome-terminal.
Use “-- ” to terminate the options and put the command line to execute after it.
Thus the preferred syntax appears to be
gnome-terminal -- echo hello
rather than
gnome-terminal -x echo hello
Here is a complete example of how you would call a executable python file with subprocess.call Using argparse to properly parse the input.
the target process will print your given input.
Your python file to be called:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("--file", help="Just A test", dest='myfile')
args = parser.parse_args()
print args.myfile
Your calling python file:
from subprocess import call
#call(["python","/users/dev/python/sandboxArgParse.py", "--file", "abcd.txt"])
call(["gnome-terminal", "-e", "python /users/dev/python/sandboxArgParse.py --file abcd.txt"])
Just for information:
You probably don't need python calling another python script to run a terminal window with a process, but could do as follows:
gnome-terminal -e "python /yourfile.py -f yourTestfile.txt"
The following code will open a new terminal and execute the process:
process = subprocess.Popen(
"sudo gnome-terminal -x python f.py",
stdout=subprocess.PIPE,
stderr=None,
shell=True
)
I am running a uWS server with this.In my case Popen didn't help(Even though it run the executable, still it couldn't communicate with a client -: socket connection is broken).This is working.Also now they recommends to use "--" instead of "-e".
subprocess.call(['gnome-terminal', "--", "python3", "server_deployment.py"])
#server_deployment.py
def run():
execution_cmd = "./my_executable arg1 arg2 dll_1 dll_2"
os.system(execution_cmd)
run()

How execute script from command prompt in python

I have mysql dump command that I would like to run from from windows shell
or command prompt. I have used shell it does work.
d= 'BkSql_'+datetime.datetime.now().strftime("%Y-%m-%d")+".sql"
fn = dn+d
cmd="""mysqldump -u hapopdy -p > %s""" %fn
print cmd
Edit:::::::
The -p needs to be a raw input.
Using the subprocess module
import subprocess
subprocess.call(cmd)
If you're running a shell command add shell=True
subprocess.call(cmd, shell=True)
You should save the password in mysql's local configuration file for the user.(In Unix it's ~/.my.cnf) or you can give it on the command line with --password=MYPASSWORD.
Either way, the password will be visible to a large audience. In the .my.cnf case, it will be visible to anyone with read access to the file. In the second case, it will be visible to anyone who can get a process listing on the system, in addition to those who have read access to your script.

Categories

Resources