Python : fork and exec a process to run on different terminal - python

I am trying to simulate a a network consisting of several clients and servers. I have written node.py which contains client-server code. I want to run multiple instances node.py. But I don't want to do it manually so I have written another file spawn.py which spawns multiple instances of node.py using fork and exec. However, I need to run each instance of node.py on different terminal(shell) so that I can easily debug what is happening inside each node.
How can we do that? Please help.
EDIT : I am working on linux and using python 2.5 and
I want to run all processes on the same box

If you want "real" (pseudo-;-) terminals, and are using X11 (almost every GUI interface on Linux does;-), you could exec xterm -e python node.py instead of just python node.py -- substitute for xterm whatever terminal emulator program you prefer, of course (I'm sure they all have command-line switches equivalent to good old xterm's -e, to specify what program they should run!-).

shell #1:
for p in 1 2 3 4 5
do
python node.py > $p.log 2>&1
done
shell #2:
tail -F 1.log
shell #3:
tail -F 2.log
etc...

Related

run new cygwin shell and kill it when I want

I've created an app that runs on cygwin, that will open some new shells and run python script on each of them. The problem started when I wanted to have control on the new shells and kill them at will. after a lot of digging I decided to use the following command:
subprocess.run('mintty.exe -t {} -h always -e {} &'.format(app_name, run_app_cmd), shell = True)
and later when I'll want to kill it use:
subprocess.run('kill -2 {}'.format(apps[app].shell_pid), shell = True).
it worked pretty well until I realized that A-L-O-T of times the new terminal gets stuck and doesn't respond, and I don't like it. I made some more digging and I found that while I thought that the python on the current mintty executes the command and opens the new terminal, what that actually happens is that the windows host opens the new mintty (the PPID of the new terminal is 1), and then probably the signal goes through some windows problems and etc.
the reason that I want each of the scripts in a separate terminal is that each of them have a lot of output, and I want them in different windows.
Now, after all this explanation, is there any way to prevent this? I don't want these stuck to become a part of my life...

Start two shell sudo scripts in two different terminals from python3

I have an embedded system on which I run code live. Every time I want to run code, I start two scripts in two different terminals: "run1.sh" and "run2.sh". I can see the output of those scripts in my terminals (I wish to too).
Now I want to make a python script that starts those two scripts in two different terminals. I want to still see their output. Also I want to insert a password from the python script to the terminals, since the scripts run in sudo mode. I've played a lot with supbrocess and the PIPES but I've never achieved all of the above requirements simultaneously. How can these requirements be met?
I'm using Ubuntu btw (so I have gnome terminal)
Update : I was probably not clear in my question, but this has to be inside a python script. It is not for my convenience, it's part of an integration process. The code of the script will be part of a larger python program, so the whole point of the question is how do I do it in python.
Based on your new information added I've created an small python script which will launch two terminals and their output separately:
Main script:
mortiz#florida:~/Documents/projects/python/split_python_execution$ cat split_pythonstuff.py
#!/usr/bin/python3
import subprocess
subprocess.call(['gnome-terminal', '-x', 'python', '/home/mortiz/Documents/projects/python/split_python_execution/script1.py'])
subprocess.call(['gnome-terminal', '-x', 'python', '/home/mortiz/Documents/projects/python/split_python_execution/script2.py'])
Script 1:
mortiz#florida:~/Documents/projects/python/split_python_execution$ cat script1.py
#!/usr/bin/python3
while True :
print ('script 1')
Script 2:
mortiz#florida:~/Documents/projects/python/split_python_execution$ cat script2.py
#!/usr/bin/python3
while True:
print ('script 2')
From here I guess you can develop anything you want.
UPDATE: About sudo
Sudoers is a great way of controlling which things can be executed by specific users providing passwords or not.
If you add this line in /etc/sudoers there's not need for a password when you pass sudo to your command:
<YOUR_USER> ALL = NOPASSWD : /usr/bin/python <SCRIPT.py>
In your question as far as I understand you have the password stored inside the script. There's no need to do that and it's a bad practice. Sudoers would be a better way.
Anyway, if you want to do it in an insecure way then refer to this question and place it before the commands in the scripts provided in this answer.
The linked provided works:
echo -e "mypassword\n" | sudo -S python test.py
15
You only need to implement that on the previous code.
You could install Terminator and configure one profile per terminal to run any script you want.
I have a default template which will load 3 terminals and run 3 different commands / or scripts if you wanted to:
When I load that profile the first one will move me to my projects dir and list them. The next one will run df -h to see the space available and the lower my ip configuration.
This way would save you lots of programming and it's quite easy.
UPDATE: It will run any command, bash, zsh, python, etc.. available for your terminal. If the script is locally in your machine:
python <your_script_1> # first terminal profile
python <your_script_2> # second terminal profile
both would be executed "at the same time".
If your scripts are remote in the target machine, simply create a bash script using ssh to connect to the remote machine with a private key and then running the script, the result is the same in both scenarios.
EDIT: The best thing is setting colors and transparency for each terminal, so you can enjoy the penguin's selfie while you work.

Using a shell script to call multiple ROS launch files

I just found out that I need a quick-and-dirty demo for tomorrow. I'm working with a robot that uses ROS, and we have some packages that make it move in a simple pattern. I want to start all the necessary nodes with one command. The command lines I would need to run--all in separate terminals--are:
roscore
rviz
roslaunch [blank move_base map]
roslaunch [package] [movement script]
rqt_graph
All of these programs run indefinitely--e.g., roscore is a server that coordinates the other nodes. I can't just use "&" to string them together into one line. They each require a dedicated terminal window/process. How can I do that in bash or Python?
Note: I realize it would probably be better to use a custom ROS launch file, but I don't have time.
You can launch your softwares from the terminal binaries themselves to get a new terminal for each. It would depend on the terminal you use. With konsole you can have
konsole -e command [args]
...
With gnome-terminal you do:
gnome-terminal -e command [args] &
With xterm:
xterm -e command [args] &
Probably refer as well to a similar thread: Run multiple .sh scripts from one .sh script? CentOS

launch external shell python instance in shell from python

I'd like to call a separate non-child python program from a python script and have it run externally in a new shell instance. The original python script doesn't need to be aware of the instance it launches, it shouldn't block when the launched process is running and shouldn't care if it dies. This is what I have tried which returns no error but seems to do nothing...
import subprocess
python_path = '/usr/bin/python'
args = [python_path, '&']
p = subprocess.Popen(args, shell=True)
What should I be doing differently
EDIT
The reason for doing this is I have an application with a built in version of python, I have written some python tools that should be run separately alongside this application but there is no assurance that the user will have python installed on their system outside the application with the builtin version I'm using. Because of this I can get the python binary path from the built in version programatically and I'd like to launch an external version of the built in python. This eliminates the need for the user to install python themselves. So in essence I need a simple way to call an external python script using my current running version of python programatically.
I don't need to catch any output into the original program, in fact once launched I'd like it to have nothing to do with the original program
EDIT 2
So it seems that my original question was very unclear so here are more details, I think I was trying to over simplify the question:
I'm running OSX but the code should also work on windows machines.
The main application that has a built in version of CPython is a compiled c++ application that ships with a python framework that it uses at runtime. You can launch the embedded version of this version of python by doing this in a Terminal window on OSX
/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python
From my main application I'd like to be able to run a command in the version of python embedded in the main app that launches an external copy of a python script using the above python version just like I would if I did the following command in a Terminal window. The new launched orphan process should have its own Terminal window so the user can interact with it.
/my_main_app/Contents/Frameworks/Python.framework/Versions/2.7/bin/python my_python_script
I would like the child python instance not to block the main application and I'd like it to have its own terminal window so the user can interact with it. The main application doesn't need to be aware of the child once its launched in any way. The only reason I would do this is to automate launching an external application using a Terminal for the user
If you're trying to launch a new terminal window to run a new Python in (which isn't what your question asks for, but from a comment it sounds like it's what you actually want):
You can't. At least not in a general-purpose, cross-platform way.
Python is just a command-line program that runs with whatever stdin/stdout/stderr it's given. If those happen to be from a terminal, then it's running in a terminal. It doesn't know anything about the terminal beyond that.
If you need to do this for some specific platform and some specific terminal program—e.g., Terminal.app on OS X, iTerm on OS X, the "DOS prompt" on Windows, gnome-terminal on any X11 system, etc.—that's generally doable, but the way to do it is by launching or scripting the terminal program and telling it to open a new window and run Python in that window. And, needless to say, they all have completely different ways of doing that.
And even then, it's not going to be possible in all cases. For example, if you ssh in to a remote machine and run Python on that machine, there is no way it can reach back to your machine and open a new terminal window.
On most platforms that have multiple possible terminals, you can write some heuristic code that figures out which terminal you're currently running under by just walking os.getppid() until you find something that looks like a terminal you know how to deal with (and if you get to init/launchd/etc. without finding one, then you weren't running in a terminal).
The problem is that you're running Python with the argument &. Python has no idea what to do with that. It's like typing this at the shell:
/usr/bin/python '&'
In fact, if you pay attention, you're almost certainly getting something like this through your stderr:
python: can't open file '&': [Errno 2] No such file or directory
… which is exactly what you'd get from doing the equivalent at the shell.
What you presumably wanted was the equivalent of this shell command:
/usr/bin/python &
But the & there isn't an argument at all, it's part of sh syntax. The subprocess module doesn't know anything about sh syntax, and you're telling it not to use a shell, so there's nobody to interpret that &.
You could tell subprocess to use a shell, so it can do this for you:
cmdline = '{} &'.format(python_path)
p = subprocess.Popen(cmdline, shell=True)
But really, there's no good reason to. Just opening a subprocess and not calling communicate or wait on it already effectively "puts it in the background", just like & does on the shell. So:
args = [python_path]
p = subprocess.Popen(args)
This will start a new Python interpreter that sits there running in the background, trying to use the same stdin/stdout/stderr as your parent. I'm not sure why you want that, but it's the same thing that using & in the shell would have done.
Actually I think there might be a solution to your problem, I found a useful solution at another question here.
This way subprocess.popen starts a new python shell instance and runs the second script from there. It worked perfectly for me on Windows 10.
You can try using screen command
with this command a new shell instance created and the current instance runs in the background.
# screen; python script1.py
After running above command, a new shell prompt will be seen where we can run another script and script1.py will be running in the background.
Hope it helps.

PyDev + mpi4py -> run through shellscript / mpirun

I'd like to create python programs that use mpi4py and thus I'd like to run them using the following command:
mpirun -np 4 python script.py
I tried to create a shell script which does this and use it as a python interpreter but eclipse rejects the shell script. I tried to redirect the output (so that it doesen't show the mpi-stuff but soley prints the python-output of the first node).
If I run the script in the console using the interpreterinfo.py script to test the interpreter it gives exactly the same output as if I run it only through python.
It somehow seems that the script isn't executed properly by eclipse or that the output is not going into stdout.
Can anyone help?
I don't think you should try to configure mpirun as the python interpreter... Instead, configure the python interpreter as usual and just create a python module that'll do the launching for you and launch that module instead... (or create an external launch in run > external tools)
It'd be strange that mpirun is the actual python interpreter, because that way when requesting a code completion for builtins, pydev would launch the mpirun and it'd create 4 processes for code-completion? The same would apply to other things such as debug, coverage, etc...

Categories

Resources