Linux Python process with visible console window - python

I have a question about Python on Linux. I have a Python application that currently runs on Windows. The application controls some hardware, and each hardware control application runs in it's own process, which in turn sometimes start processes of their own. The processes communicate with named pipes, named mutexes, and named memory-mapped files to the main control process, but each application process has its own console window. This allows the user to select the window for one application process, representing one hardware item, and view what it's doing. It also allows a simple "print" to produce debug statements on the window for that process. On Windows this is easy because either os.startfile or subprocess.popen can run a python script in a separate process, in a new console window, and capturing "print" output in that window. The main process starts all the application processes and then minimizes the windows, making it easy for the user to select one (or more) for viewing. The application processes write log files when they are done, but having a console window for each one allows viewing of progress and messages in real time.
I need to make a linux version of this and I'm running into issues. I can't figure out how to make Linux open an application in a separate, visible, process window. If I use subprocess.popen with shell=True, I get a separate process but no visible window. If I set stdout=subprocess.PIPE, the application isn't in a separate process, but uses the main process window for printing, and incidentally hangs the main process until it's done (this is disasterous in my application). I found a workaround where I open the application process with shell=True, and the application process then creates a named pipe and opens its own GUI (using shell=True) for output display. But this means I have to change all the print statements in the application processes to go to the named pipe, which is a huge amount of work. Plus, it would be nice (but not essential) if the Windows and Linux versions looked the same in how the windows appear.
Is there a way, in Python, on Linux, to start a new Python process in an open, visible window that will capture "print" statements? Or am I trying to do something Linux doesn't support? I'd rather not change everything to sockets - it would probably be easier to use the GUI and named pipe method than to do that.
Thanks for any answers or insight.

Related

Open and killing processes on mac

Opened program doesnt shutdown when called upon with terminate() on macOS.
I tried to open an external file through python, and then closing it. Everything seems to be working except for killing the process (application) on macOS. How to kill it?
prog = subprocess.Popen(['open', FileName])
while True:
if keyboard.is_pressed("q"):
prog.terminate()
break
Not so easy.
In mac, the open command will dig up the system to find an application to launch your file, which means it will fork-exec another executable as a new process. Once it is done, the open command will terminate while leaving the other process run (in the background, as orphaned process).
So using the subprocess context, you will see the process ID of open but not the process ID of the child process that open launched. Moreover, consider the case that open launches a directory, which on Mac it will be opened as a new window on Finder. Then you have no new process ID created! Similarly for other files if the application invoked already running before you called open and it prefers to open the new file in new tabs of existing process instead.
In your situation, if you want a better control, probably you need to figure out the right application to open your file, and launch it directly instead of relying on open.
Edit:
This is the man page of open. You may use some switch to make open running until the child process terminates and so on. But still, I am not sure you can kill the child processes by killing open (whether or not that succeed depends on a lot of factors). Probably you need to figure out the process IDs of the child processes and kill them directly.

Keeping a program going on an external server

I have an external server that I can SSH into. It runs bots on reddit.
Whenever I close the terminal window the bot is running in, the process stops, which means the bot stops as well.
I've tried using
nohup python mybot.py
but it doesn't work - when I close the window and check the processes (ps -e), python does not show up. Are there any alternatives to nohup? Ideally, that print the output to the terminal, instead of an external file.
Have you considered using tmux/screen? They have lots of features and can help you detach a terminal and re-attach to it at a later date without disrupting the running process.

Moving CMD python app to the system tray (windows)

I have an python 2.7 application that I would like to move from the CMD window to the system/notification tray (Windows 7). The python script currently listens for particular TCP messages, and upon receipt, logs them to a file.
I have recently found the following system tray code, from another question answered here:
systrayicon
I've been able to run the systrayicon demo correctly by creating the SysTrayIcon.py module. My problem is, when I try to run my TCP application alongside the systrayicon (with some of the demo code intact), it only runs my application, or the system tray application, not both. More specifically, if I list my app's main(sys.argv) before the systrayicon(), it only runs my app without the tray icon. If I have the systrayicon listed before my app, it runs the system tray demo, until I select "Quit", and it then runs my app.
I am able to get my TCP app to run correctly if I plug it into one of the menu selection functions, for example:
def hello(sysTrayIcon):
main(sys.argv)
But I'd like my app to begin listening when the application is opened, without selecting something from the menu to initiate it.
This is likely a very basic problem, and maybe worded poorly, my apologies.
I think the easiest way for you to accomplish this would be to just wrap your script with a small piece of GUI code using Tkinter or wxPython. Then it can reside in the tray. You will probably need to run your script in a thread as it sounds like a long running process that would block the toolkit's main loop. You might need to add some code to the threading code that allows you to kill your script when the GUI exits, but other than that, it should be pretty easy.

jython killing parent process that spawns subprocess breaks subprocess stdout to file?

Let me start with what I'm really trying to do. We want a platform independent startup script for invoking a JVM with some system properties and a dynamically generated classpath. We picked Jython in particular because we only need to depend on the standalone jython.jar in our startup script. We decided we could write a jython script that uses subprocess.Popen to launch our application's jvm and then terminates.
One more thing. Our application uses a lot of legacy debug code that prints to standard out. So the startup script typically has been redirecting stdout/stderr to a log file. I attempted to reproduce that with our jython script like this:
subprocess.Popen(args,stdout=logFile,stderr=logFile)
After this line the launcher script and hosting jvm for jython terminates. The problem is nothing shows up in the logFile. If I instead do this:
subprocess.Popen(args,stdout=logFile,stderr=logFile).wait()
then we get logs. So the parent process needs to run parallel to the application process launched via subprocess? I want to avoid having two running jvms.
Can you invoke subprocess in such a way that the stdout file will be written even if the parent process terminates? Is there a better way to launch the application jvm from jython? Is Jython a bad solution anyway?
We want a platform independent startup script for invoking a JVM with some system properties and a dynamically generated classpath.
You could use a platform independent script to generate a platform specific startup script either at installation time or before each invocation. In the latter case, additionally, you need a simple static platform specific script that invokes your platform independent startup-script-generating script and then the generated script itself. In both cases you start your application by calling a static platform specific script.
Can you invoke subprocess in such a way that the stdout file will be written even if the parent process terminates?
You could open file/redirect in a child process e.g., using shell:
Popen(' '.join(args+['>', 'logFile', '2>&1']), # shell specific cmdline
shell=True) # on Windows see _cmdline2list to understand what is going on

GTK+ Startup Notification Icon

In Gnome, whenever an application is started, the mouse cursor changes from normal to an activity indicator (a spinning wheel type thing on Ubuntu). Is there any way to inform Gnome (through some system call) when the application has finished launching so that the mouse cursor returns to normal without waiting for the usual timeout of 30 seconds to occur.
I have a program in Pythong using GTK+ that is showing the icon even after launching, so what system call do I make?
Normally it happens automatically when you open the application's window.
It may be that the application's launcher just calls an already running instance, in that case it won't be automatically detected. The call you need then is this:
import gtk
gtk.gdk.notify_startup_complete()
Your application can opt out of startup notification by adding
StartupNotify=false
to your application's .desktop file.
Of course, it is friendlier to leave it enabled and participate in startup notification.
I had a similar issue with an application I wrote. I was launching the application through a shell script containing the line
python /path/to/application.py
This launched the application as I expected, but the startup notification did not stop.
It worked correctly once I changed the content of my script to this:
exec "/usr/bin/python" "/path/to/application.py"
Obviously the latter one seems to be the correct way to launch the application, though I don't have enough insight to tell why.
This normally happens automatically when calling the gtk.main() function

Categories

Resources