How to start a background process in Python?

后端 未结 7 580
庸人自扰
庸人自扰 2020-11-22 02:44

I\'m trying to port a shell script to the much more readable python version. The original shell script starts several processes (utilities, monitors, etc.) in the background

7条回答
  •  悲&欢浪女
    2020-11-22 03:12

    Both capture output and run on background with threading

    As mentioned on this answer, if you capture the output with stdout= and then try to read(), then the process blocks.

    However, there are cases where you need this. For example, I wanted to launch two processes that talk over a port between them, and save their stdout to a log file and stdout.

    The threading module allows us to do that.

    First, have a look at how to do the output redirection part alone in this question: Python Popen: Write to stdout AND log file simultaneously

    Then:

    main.py

    #!/usr/bin/env python3
    
    import os
    import subprocess
    import sys
    import threading
    
    def output_reader(proc, file):
        while True:
            byte = proc.stdout.read(1)
            if byte:
                sys.stdout.buffer.write(byte)
                sys.stdout.flush()
                file.buffer.write(byte)
            else:
                break
    
    with subprocess.Popen(['./sleep.py', '0'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc1, \
         subprocess.Popen(['./sleep.py', '10'], stdout=subprocess.PIPE, stderr=subprocess.PIPE) as proc2, \
         open('log1.log', 'w') as file1, \
         open('log2.log', 'w') as file2:
        t1 = threading.Thread(target=output_reader, args=(proc1, file1))
        t2 = threading.Thread(target=output_reader, args=(proc2, file2))
        t1.start()
        t2.start()
        t1.join()
        t2.join()
    

    sleep.py

    #!/usr/bin/env python3
    
    import sys
    import time
    
    for i in range(4):
        print(i + int(sys.argv[1]))
        sys.stdout.flush()
        time.sleep(0.5)
    

    After running:

    ./main.py
    

    stdout get updated every 0.5 seconds for every two lines to contain:

    0
    10
    1
    11
    2
    12
    3
    13
    

    and each log file contains the respective log for a given process.

    Inspired by: https://eli.thegreenplace.net/2017/interacting-with-a-long-running-child-process-in-python/

    Tested on Ubuntu 18.04, Python 3.6.7.

提交回复
热议问题