The exec command replaces the currently running process with a new one, so if you have an exec in a list of commands to run, as soon as exec is run, nothing else will run. So you're replacing 'bash -c \"exec bash; MY_COMMAND; exec bash\" ' with bash, and then nothing after the exec bash is running. Try this instead:
os.system("gnome-terminal -e 'bash -c \"MY_COMMAND\" '")
or if you need a terminal to stay open, try this:
os.system("gnome-terminal -e 'bash -c \"MY_COMMAND; sleep 1000000\" '")
of if you want the terminal to stay open and be in a bash shell, try this:
os.system("gnome-terminal -e 'bash -c \"MY_COMMAND; bash\" '")
Answer from Christopher Shroba on Stack OverflowThe exec command replaces the currently running process with a new one, so if you have an exec in a list of commands to run, as soon as exec is run, nothing else will run. So you're replacing 'bash -c \"exec bash; MY_COMMAND; exec bash\" ' with bash, and then nothing after the exec bash is running. Try this instead:
os.system("gnome-terminal -e 'bash -c \"MY_COMMAND\" '")
or if you need a terminal to stay open, try this:
os.system("gnome-terminal -e 'bash -c \"MY_COMMAND; sleep 1000000\" '")
of if you want the terminal to stay open and be in a bash shell, try this:
os.system("gnome-terminal -e 'bash -c \"MY_COMMAND; bash\" '")
Here we go...
command="python3 --version"
os.system("gnome-terminal -e 'bash -c \""+command+";bash\"'")
That should do it...
Output:Python 3.6.4
And the output came into a new terminal....
Open terminal and write in it from python script
bash - How can I make a script that opens terminal window, executes commands in it and remains open on Scientific Linux? - Unix & Linux Stack Exchange
open a terminal from python - Stack Overflow
shell - Execute terminal command from python in new terminal window? - Stack Overflow
Videos
The following python code will run a command-line-based software (shown in the "cmd" string) in the background which takes a long time.
May I ask how to use python to open a new terminal window and run the same command in it, so that the main python code can move on to process other things without being blocked here?
Thanks.
cmd = 'las2txt64 -i point_cloud_data.las -o output.csv -parse xyzRGBinrc -sep comma'
with open('output.txt', 'w') as f:
run_las = subprocess.Popen(
cmd,
shell=True,
stderr=f,
text=True,
)
run_las.wait()You could do this:
os.system("gnome-terminal -e 'bash -c \"sudo apt-get update; exec bash\"'")
There are a few choices:
- add
; read -p "Hit ENTER to exit"to the end of the command line. - add
; sleep 10to the end of the command line to wait a bit, then exit. Configure gnome terminal:
Go to the "Edit" menu and click "Current Profile". Click on the "Title and Command" tab. In there, there is a setting called "When command exits". Change it to "hold the terminal open". You could also create a new profile.
This one should work:
gnome-terminal -e "python3 /path/to/script.py"
To run an application in a system's default terminal we may define a .desktop file we can then add to our startup applications in ~/.config/autostart with the following content:
[Desktop Entry]
Encoding=UTF-8
Name=Name of Application
Exec=python3 path/to/application.py
Terminal=true
Type=Application
StartupNotify=true
NoDisplay=true
Note that the terminal will close on termination of our script only if our terminal profile is set to do so (default in gnome-terminal but editable from profile settings).
There's no way to do this in general from a shell. What you have to do is run the terminal program itself, or some launcher program that does so for you. And the way to do that is different for each terminal program.
In some cases, os.startfile will do what you want, but this isn't going to be universal.
Also, note in general, you're going to actually need an absolute path to your script, because the new terminal window will be running a new shell and therefore won't necessarily have your same working directory. But I'll ignore that for the examples.
With Windows cmd, the easiest way to do it is the start shell command. If the thing you start is any command-line program, including python, it will get a new cmd window. So, something like:
subprocess.call('start /wait python bb.py', shell=True)
OS X has a similar command, open. And it's a real program rather than a shell command, so you don't need shell=True. However, running a command-line program or script with open doesn't generally open a new terminal window. In fact, the whole point of it is to allow you to run programs as if they were being double-clicked in Finder, which never runs something in the terminal unless it's a .command file.
So, you can create a temporary .command wrapper file and open that; something like this (untested):
with tempfile.NamedTemporaryFile(suffix='.command') as f:
f.write('#!/bin/sh\npython bb.py\n')
subprocess.call(['open', '-W', f.name])
Alternatively, you can explicitly tell open to use Terminal.app, something like this:
subprocess.call(['open', '-W', '-a', 'Terminal.app', 'python', '--args', 'bb.py'])
Or you can script Terminal.app via AppleEvents. For example:
appscript.app('Terminal').do_script('python bb.py')
The "do script" event opens a new window and runs its argument as a command. If you want more detailed control, open the scripting dictionary in AppleScript Editor and see all the fun stuff you can do.
On Linux or other *nix systems… well, there are 65,102 different desktop environments, launchers, and terminal programs. Do you need to work on all of them?
With gnome-terminal, just running the terminal again gives you a new window, and the -x argument lets you specify an initial command, so:
subprocess.call(['gnome-terminal', '-x', 'python bb.py'])
Many older terminals try to be compatible with xterm, which does the same thing with -e, so:
subprocess.call(['xterm', '-e', 'python bb.py'])
subprocess.call(['rxvt', '-e', 'python bb.py'])
… etc.
How do you know which terminal the user is using? Good question. You could walk the like of parent processes from yourself until you find something that looks like a terminal. Or you could just assume everyone has xterm. Or you could look at how various distros configure a default terminal and search for all of them. Or…
This should probably be a comment, but since I can't yet...
In Windows , you can do:
subprocess.call('python bb.py', creationflags=subprocess.CREATE_NEW_CONSOLE)
There are several ways to do this:
A simple way is using the os module:
import os
os.system("ls -l")
More complex things can be achieved with the subprocess module: for example:
import subprocess
test = subprocess.Popen(["ping","-W","2","-c", "1", "192.168.1.70"], stdout=subprocess.PIPE)
output = test.communicate()[0]
I prefer usage of subprocess module:
from subprocess import call
call(["ls", "-l"])
Reason is that if you want to pass some variable in the script this gives very easy way for example take the following part of the code
abc = a.c
call(["vim", abc])
You can use os.system(), like this:
import os
os.system('ls')
Or in your case:
os.system('echo 1 > /proc/sys/net/ipv4/ip_forward')
os.system('iptables -t nat -A PREROUTING -p tcp --destination-port 80 -j REDIRECT --to-port 8080')
Better yet, you can use subprocess's call, it is safer, more powerful and likely faster:
from subprocess import call
call('echo "I like potatos"', shell=True)
Or, without invoking shell:
call(['echo', 'I like potatos'])
If you want to capture the output, one way of doing it is like this:
import subprocess
cmd = ['echo', 'I like potatos']
proc = subprocess.Popen(cmd, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
o, e = proc.communicate()
print('Output: ' + o.decode('ascii'))
print('Error: ' + e.decode('ascii'))
print('code: ' + str(proc.returncode))
I highly recommend setting a timeout in communicate, and also to capture the exceptions you can get when calling it. This is a very error-prone code, so you should expect errors to happen and handle them accordingly.
https://docs.python.org/3/library/subprocess.html
The first command simply writes to a file. You wouldn't execute that as a shell command because python can read and write to files without the help of a shell:
with open('/proc/sys/net/ipv4/ip_forward', 'w') as f:
f.write("1")
The iptables command is something you may want to execute externally. The best way to do this is to use the subprocess module.
import subprocess
subprocess.check_call(['iptables', '-t', 'nat', '-A',
'PREROUTING', '-p', 'tcp',
'--destination-port', '80',
'-j', 'REDIRECT', '--to-port', '8080'])
Note that this method also does not use a shell, which is unnecessary overhead.