simplest way to make two python scripts talk to each other? - python

I have a python script running on a vps. Now i just want to change 1 variable in the running script using my desktop computer.
What is the simplest way to that for a beginner?

If I were a beginner, I would have my remote script periodically check the value of the variable in a text file. When I needed to update the variable, I would just ssh to my remote machine and update the text file.

Using a text file that is polled at a regular interval is an easy way to go.
A more efficient and probably easier way is to register a signal handler in your python process that would force the process to reload the value in the text file when demanded rather than continuously polling. On linux you can use the kill command in the terminal to send the a signal after updating the file. This is actually probably simpler than implementing continuous polling.
import signal
import sys
import os
print os.getpid()
def signal_handler(signal, frame):
# open text file and check for new value
print "value reset"
signal.signal(signal.SIGUSR1, signal_handler)
Then in Linux terminal to trigger the value to be reloaded you can do:
kill -SIGUSR1 pidprinted
If you wanted to get really fancy, you could register a signal handler to start pdb (python's debugger), inject the value into the running process, and continue, but I think doing the above is easiest.

Related

Python & subprocess - Open terminal session as user and execute one/two commands

As much as I hate regurgitating questions, it's a necessary evil to achieve a result to the next issue I'll present.
Using python3, tkinter and the subprocess package, my goal is to write a control panel to start and stop different terminal windows with a specific set of commands to run applications/sessions of the ROS application stack, including the core.
As such, the code would look like this per executable I wish to control:
class TestProc(object):
def __init__(self):
pass
def start(self):
self.process = subprocess.Popen(["gnome-terminal", "-c", "'cd /path/to/executable/script.sh; ./script.sh'"])
print("Process started.")
def stop(self):
self.process.terminate()
print("Process terminated.")
Currently, it is possible to start a terminal window and the assigned commands/processes, yet two issues persist:
gnome-terminal is set to launch a terminal window, then relieve control to the processes inside; as such, I have no further control once it has started. A possible solution for this is to use xterm yet that poses a slew of other issues. I am required to have variables from the user's .bashrc and/or export
Certain "global commands" eg. cd or roslaunch would be unavailable to the terminal sessions, perhaps due to the order of execution (eg. the commands are run before the bash profile is loaded) preventing any usable terminal at all
Thus, the question rings: How would I be able to start and stop a new terminal window that would run up to two commands/processes in the user environment?
There are a couple approaches you can take, the most flexible here is also the most complicated, so you'd want to consider whether you need to do it.
If you only need to show the output of the script, you can simply pipe the output to a file or to a named pipe. You can then capture that output by reading/tailing the file. This is simplest, as long as the script don't actually need to have any user interaction.
If you really only need to spawn a script that runs in the background, and you need to simulate user interaction but you don't actually need to accept actual user input, you can use expect approach (using the pexpect library).
If you need to actually allow the real user to interact with the program, then you have two approaches. First is that you can embed the VTE widget into your application, this is the most seamless integration as it'll make the terminal look seamless with your application, however it's also the most heavy.
Another approach is to start gnome-terminal as you've done here, this necessarily spawns a new window.
If you need to both script some interaction while also allowing some user input, you can do this by spawning your script in a tmux session. Using tmux send-keys command to automate the moon interactive part, and then spawn a terminal emulator for users to interact with tmux attach. If you need to go back and forth between automated part and interactive part, you can combine this approach with expect.

Close console while process is running

I'm writing a small application that uses an "index-file" to open folders in explorer from just a few button presses. Anyway I would like to update that index file in a "background process" every time the applications shuts down. Updating the index file means scanning through our network and for some remote users it could take a few minutes. That's why I would like it to hide the console during the scanning process in order to avoid the process being aborted by user.
I tried several things similar to:
#these are just dummy lines
path = get_user_input()
subprocess.Popen(r'explorer "%s"' % path)
#Here I start my update process
multiprocessing.Process(target=update_index).start()
#end of script, now I want that process to continue until finished while main console closes. I only seem to get one or the other.
I also tried using:
DETACHED_PROCESS = 0x00000008
CREATE_NO_WINDOW = 0x08000000
subprocess.Popen(command, shell=True, stdin=None, stdout=None,
stderr=None,
creationflags=DETACHED_PROCESS|CREATE_NO_WINDOW)
and managed to get a separate console window but still no way from preventing the user for closing down the process.
Also keep in mind I would like to distribute this script with something like py2exe later to make it accessible for those without python so I guess using pythonw.exe is out of question. or?
That's not really the answer you're looking for, but you could redesign your system architecture: Write your index updater as a server process that's communicating with your actual application over sockets. Then you just have the index updater server process run continuously (maybe even on another machine) and have the index updater process do all the time-consuming work.
If you just want to perform background tasks that happen at certain intervals, then use cron. If you want to run a command in the background and keep it running even if you logout of the console, use nohup.

How to check which line of a Python script is being executed?

I've got a Python script which is running on a Linux server for hours, crunching some numbers for me. I'd like to check its progress, so I'd like to see what line is being executed right now. If that was a C or C++ program then I would just attach to the process with gdb -p <pid> and examine the stacktrace with where. Of course, I can do the same with the Python interpreter process, but I can't see the Python script's line in the stacktrace.
So, how can I find out which line of the Python script is being executed currently?
You can add a signal handler to the Python script that sends this information to the terminal, or to a file, then hit ^C in the terminal to send the signal to the process.
import signal
def print_linenum(signum, frame):
print "Currently at line", frame.f_lineno
signal.signal(signal.SIGINT, print_linenum)
You could also use some other signal and use the kill command to send the signal, if you need ^C to be able to interrupt the script, or set a signal.alarm() to print the information periodically, e.g. once a second.
You could print out other things from the stack frame if you like; there's a lot there. See the attributes of frame objects in this table.

Sending commands from one xterm window to another with Python

So I have a Python app that starts different xterm windows and in one window after the operation is finished it asks the user "Do you want to use these settings? y/n".
How can I send y to that xterm window, so that the user doesn't needs to type anything.
Thanks
If you are on linux (kde) and you just want to control the xterms by sending commands between them, you could try using dcop:
http://www.linuxjournal.com/content/start-and-control-konsole-dcop
http://www.riverbankcomputing.co.uk/static/Docs/PyKDE3/dcopext.html
Otherwise you would need to actually use an inter-process communication (IPC) method between the two scripts as opposed to controlling the terminals:
http://docs.python.org/library/xmlrpclib.html
http://docs.python.org/library/ipc.html
Some other IPC or RPC library
Simply listen on a basic socket and wait for ANYTHING. And then from the other app open a socket and write SOMETHING to signal.
Or at a very very basic level, you could have one script wait on file output from the other. So once your first xterm finishes, it could write a file that the other script sees.
These are all varying difficulties of solutions.

How can I detect what other copy of Python script is already running

I have a script. It uses GTK. And I need to know if another copy of scrip starts. If it starts window will extend.
Please, tell me the way I can detect it.
You could use a D-Bus service. Your script would start a new service if none is found running in the current session, and otherwise send a D-Bus message to the running instace (that can send "anything", including strings, lists, dicts).
The GTK-based library libunique (missing Python bindings?) uses this approach in its implementation of "unique" applications.
You can use a PID file to determine if the application is already running (just search for "python daemon" on Google to find some working implementations).
If you detected that the program is already running, you can communicate with the running instance using named pipes.
The new copy could search for running copies, fire a SIGUSER signal and trigger a callback in your running process that then handles all the magic.
See the signal library for details and the list of things that can go wrong.
I've done that using several ways depending upon the scenario
In one case my script had to listen on a TCP port. So I'd just see if the port was available it'd mean it is a new copy. This was sufficient for me but in certain cases, if the port is already in use, it might be because some other kind of application is listening on that port. You can use OS calls to find out who is listening on the port or try sending data and checking the response.
In another case I used PID file. Just decide a location and a filename, and everytime your script starts, read that file to get a PID. If that PID is running, it means another copy is already there. Otherwise create that file and write your process ID in it. This is pretty simple. If you are using django then you can simply use django's daemonizer: "from django.utils import daemonize". Otherwise you can use this script: http://www.jejik.com/articles/2007/02/a_simple_unix_linux_daemon_in_python/

Categories