Bring the Current Python Program to Background

Bring the current Python program to background

Update: To properly daemonize your process, use daemonize.

Original answer: Since the shell is waiting for your process to finish, the main process must terminate. You can use os.fork() to fork off a child process and sys.exit() from the parent process:

import os
import sys

if os.fork():
sys.exit()
# Child code goes here

How to constantly run Python script in the background on Windows?

On Windows, you can use pythonw.exe in order to run a python script as a background process:

Python scripts (files with the extension .py) will be executed by
python.exe by default. This executable opens a terminal, which stays
open even if the program uses a GUI. If you do not want this to
happen, use the extension .pyw which will cause the script to be
executed by pythonw.exe by default (both executables are located in
the top-level of your Python installation directory). This suppresses
the terminal window on startup.

For example,

C:\ThanosDodd\Python3.6\pythonw.exe C:\\Python\Scripts\moveDLs.py

In order to make your script run continuously, you can use sched for event scheduling:

The sched module defines a class which implements a general purpose
event scheduler

import sched
import time

event_schedule = sched.scheduler(time.time, time.sleep)

def do_something():
print("Hello, World!")
event_schedule.enter(30, 1, do_something, (sc,))

event_schedule.enter(30, 1, do_something, (s,))
event_schedule.run()

Now in order to kill a background process on Windows, you simply need to run:

taskkill /pid processId /f

Where processId is the ID of the process you want to kill.

How to run python program in background to keep active window the same

Although pythonw does run the script in the background without opening a command prompt window, your batch file does (even if this window is minimized). So you'll have to find the window that was active before your batch file was executed.

We use the EnumWindows function to iterate over our normal (i.e. visible and with a title) windows. The previous window is the second one in the enumeration. However, if you run the python script from a batch file, the command prompt window (as explained above) will be the previous window, so the one we're looking for is the third one in the enumeration.

#! python

import win32api
import win32gui
import win32con

monitors = win32api.EnumDisplayMonitors()
monitorsDict = {}

window_counter = [0]
def enumWindowsProc(hwnd, param):
if win32gui.IsWindowVisible(hwnd) and win32gui.GetWindowTextLength(hwnd) > 0:
window_counter[0] += 1
print(win32gui.GetWindowText(hwnd))
if window_counter[0] == 3:
window_counter[0] = hwnd
return False
return True

try:
win32gui.EnumWindows(enumWindowsProc,window_counter)
except:
pass

hwnd = window_counter[0]
currentWindowDimensions = win32gui.GetWindowRect(hwnd)
monitorInFocus = str(win32api.MonitorFromWindow(hwnd))

for i in range(len(monitors)):
monitorsDict[str(monitors[i][0])] = monitors[i][2]

maxWidth = (monitorsDict[monitorInFocus][2]-monitorsDict[monitorInFocus][0]) * .85
maxHeight = (monitorsDict[monitorInFocus][3]-monitorsDict[monitorInFocus][1]) * .85
x = int(currentWindowDimensions[0])
y = int(currentWindowDimensions[1])
newWidth = int(maxWidth + x)
newHeight = int(maxHeight + y)
newDimensions = (x, y, newWidth, newHeight)
win32gui.SetWindowPos(hwnd, win32con.HWND_NOTOPMOST, x, y, newWidth, newHeight, 0)

EnumWindows calls the callback function pass to it until this returns False. Unfortunately there's a bug in the win32 implementation: when the callback returns False, EnumWindows return 0 and this 0 is mistakenly considered an error and python will raise a run time error. A workaround is ignoring this error (as shown here) or just never return False and thus enumerate the windows list till the very end although we've already found our window.

Instead of using a batch file, there's a more elegant way to invoke your script without creating an extra batch file: in the shortcut on your desktop, you can just insert the one line C:\path\to\pythonw\executable\pythonw.exe C:\path\to\pyw\script\WindowSizing.pyw as the target. But remember, in this case we need to look for window number 2 instead of 3, so it'll be C:\path\to\pythonw\executable\pythonw.exe C:\path\to\pyw\script\WindowSizing.pyw.

I tested both approaches (batch file and direct shortcut target) on Windows 7 and both work fine, invocated by short cut key or by clicking on the icon on the desktop.

Running Python Script as a Windows background process

On Windows, you can run a Python script in the background using the pythonw.exe executable, which will run your program with no visible process or way to interact with it. You also cannot terminate it without a system monitor. More information on pythonw.exe can be found in the answers to the question: pythonw.exe or python.exe?

Running program/function in background in Python

As I understand it, your goal is to start a background process in subprocess but not have the main program wait for it to finish. Here is an example program that does that:

$ cat script.py
import subprocess
subprocess.Popen("sleep 3; echo 'Done!';", shell=True)

Here is an example of that program in operation:

$ python script.py
$
$
$ Done!

As you can see, the shell script continued to run after python exited.

subprocess has many options and you will want to customize the subprocess call to your needs.

In some cases, a child process that lives after its parent exits may leave a zombie process. For instructions on how to avoid that, see here.

The alternative: making subprocess wait

If you want the opposite to happen with python waiting for subprocess to complete, look at this program:

$ cat script.py
import subprocess
p = subprocess.Popen("sleep 3; echo 'Done!';", shell=True)
p.wait()

Here is an example its output:

$ python script.py
Done!
$
$

As you can see, because we called wait, python waited until subprocess completed before exiting.

Run programs in background and redirect their outputs to file in real time

The -u switch and the equivalent PYTHONUNBUFFERED environment variable forces stdout to be unbuffered. Try this:

#!/bin/bash
python -u 1.py > 1.output &
python -u 2.py > 2.output &
python -u 3.py > 3.output &

or

#!/bin/bash
export PYTHONUNBUFFERED=yes
python 1.py > 1.output &
python 2.py > 2.output &
python 3.py > 3.output &

Note that -u has side effects: read the doc to learn more.

Reference:

  • https://docs.python.org/2/using/cmdline.html#cmdoption-u
  • https://docs.python.org/2/using/cmdline.html#envvar-PYTHONUNBUFFERED

How to start another program and keep it running after Python script finishes?

The solution is actually easier then it seemed :]

We can just use os.popen to run command in cmd/pipe, this will make those processes not dependent on the python process!
So let's just do it:

import os

os.popen("notepad.exe")
os.popen("notepad.exe")

print("Bye! Now it's your responsibility to close new process(es) :0")

this served as my inspiration, tho this solution works a little differently


Windows-only:

Also if you don't want to run several Popen's (through os.popen) to open one cmd.exe and use it instead:

import subprocess
from time import sleep

path = r"C:\Windows\System32\cmd.exe"
p = subprocess.Popen(
[path],
bufsize=-1,
stdout=subprocess.PIPE,
stderr=subprocess.PIPE,
stdin=subprocess.PIPE)

def comunicate(process, message):
process.stdin.write(message)
process.stdin.flush()

comunicate(p, b'notepad.exe\n')
comunicate(p, b'notepad.exe\n')

sleep(0.1)
comunicate(p, b'exit\n') # closes cmd

print("Bye! Now it's your responsibility to close new process :0")

How to start a background process in Python?

Note: This answer is less current than it was when posted in 2009. Using the subprocess module shown in other answers is now recommended in the docs

(Note that the subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using these functions.)


If you want your process to start in the background you can either use system() and call it in the same way your shell script did, or you can spawn it:

import os
os.spawnl(os.P_DETACH, 'some_long_running_command')

(or, alternatively, you may try the less portable os.P_NOWAIT flag).

See the documentation here.



Related Topics



Leave a reply



Submit