【问题标题】:Tracking application launched with a python file使用 python 文件启动的跟踪应用程序
【发布时间】:2016-04-30 18:23:25
【问题描述】:

我遇到了一种情况,我认为这样做是个好主意 为我倾向于运行多个实例的应用程序创建一个启动器 的。这是为了确保我和应用程序能够访问想要的 可以为每个实例提供和设置的环境变量。

import os
import subprocess


def launch():
    """
    Launches application.
    """
    # create environment
    os.environ['APPLICATION_ENVIRON'] = 'usr/path'

    # launch application
    application_path = 'path/to/application'
    app = subprocess.Popen([application_path])
    pid = app.pid
    app.wait()

    print 'done with process: {}'.format(pid)


if __name__ == '__main__':
    launch()

我希望能够跟踪应用程序,是否将 pid 转储到一个文件中,然后 当进程关闭时删除它们?我是否启动了一项我可以交流的服务 和?

一般来说,我对编程相当陌生,我不知道我是否错过了一个术语 用行话或只是想错了。但我正在阅读守护进程和 跟踪应用程序的服务,但无法提供适当的 回答。简而言之,有点迷失了如何接近它。

【问题讨论】:

  • 几个问题:“我希望能够跟踪应用程序”——“跟踪它们”是什么意思? “...我倾向于运行几个实例”——您事先知道要运行多少个实例吗?您能否让您的 Python 脚本继续运行并根据需要使用其输入来启动更多进程?
  • @TomDalton 通过跟踪我的意思是我希望能够以某种方式联系他们,并且无法知道我将要启动多少个实例。是的,这是可能的。

标签: python windows launch


【解决方案1】:

你正在做的事情看起来已经很合理了。我可能会将其扩展为这样的:

import os
import subprocess


def launch_app():
    os.environ['APPLICATION_ENVIRON'] = 'usr/path'
    application_path = 'path/to/application'
    return subprocess.Popen([application_path])


def _purge_finished_apps(apps):
    still_running = set()
    for app in apps:
        return_code = app.poll()
        if return_code is not None:
            print "  PID {} no longer running (return code {})".format(app.pid, return_code)
        else:
            still_running.add(app)
    return still_running


def ui():
    apps = set()

    while True:
        print
        print "1. To launch new instance"
        print "2. To view all instances"
        print "3. To exit, terminating all running instances"
        print "4. To exit, leaving instances running"
        opt = int(raw_input())

        apps = _purge_finished_apps(apps)

        if opt == 1:
            app = launch_app()
            apps.add(app)
            print "  PID {} launched".format(app.pid)

        elif opt == 2:
            if not apps:
                print "There are no instances running"
            for app in apps:
                print "  PID {} running".format(app.pid)

        elif opt == 3:
            for app in apps:
                print "Terminating PID {}".format(app.pid)
                app.terminate()
            for app in apps:
                app.wait()
                print "PID {} finished".format(app.pid)
            return

        elif opt == 4:
            return


if __name__ == "__main__":
    ui()

【讨论】:

    【解决方案2】:

    这是一个代码示例,可帮助说明它如何为您工作。

    请注意,您可以在主机脚本中实时捕获进程的标准输出;如果您正在运行的程序使用控制台,这可能很有用。

    (作为示例的附注:您可能想要更改 IP 地址:这些来自我的内部网络。请善待您可能想要使用的任何外部站点。启动数千个相同的进程目标可能被解释为敌对姿态。)

    (此示例的附加说明:可以想象,在评估输出管道时,我会丢失一些时间样本……如果子进程将其零碎地写入控制台,可以想象我可能偶尔会捕捉到它完全按照它的中途完成 - 这意味着我可能会得到一半的“time = xxms”语句,导致RE错过它。我在检查这种可能性方面做得很差(即我不能为例子)。这是多进程/多线程编程的危险之一,如果你经常这样做,你需要注意它。)

    # Subprocessor.py
    #
    # Launch a console application repeatedly and test its state.
    #
    
    import subprocess
    import re
    
    
    NUMBER_OF_PROCESSES_TO_OPEN = 3
    DELAY_BETWEEN_CHECKS = 5
    CMD = "ping"
    ARGS = ([CMD, "-n", "8", "192.168.0.60"], [CMD, "-n", "12", "192.168.0.20"], [CMD, "-n", "4", "192.168.0.21"])
    
    def go():
        processes = {}
        stopped = [False, False, False]
    
        samples = [0]*NUMBER_OF_PROCESSES_TO_OPEN
        times = [0.0]*NUMBER_OF_PROCESSES_TO_OPEN
    
        print "Opening processes..."
        for i in range(NUMBER_OF_PROCESSES_TO_OPEN):
    
            # The next line creates a subprocess, this is a non-blocking call so
            # the program will complete it more or less instantly.
    
            newprocess = subprocess.Popen(args = ARGS[i], stdout = subprocess.PIPE)
            processes[i] = newprocess
            print "    process {} open, pid == {}.".format(i, processes[i].pid)
    
        # Build a regular expression to work with the stdout.
        gettimere = re.compile("time=([0-9]*)ms")
    
        while len(processes) > 0:
            for i, p in processes.iteritems():
    
                # Popen.poll() asks the process if it is still running - it is
                # a non-blocking call that completes instantly.
                isrunning = (p.poll() == None)
    
                data = p.stdout.readline()  # Get the stdout from the process.
                matchobj = gettimere.search(data)
                if matchobj:
                    for time in matchobj.groups():
                        samples[i] += 1
                        times[i] = (times[i] * (samples[i] - 1) + int(time)) / samples[i]
    
                # If the process was stopped before we read the last of the
                # data from its output pipe, flag it so we don't keep messing
                # with it.
                if not isrunning:
                    stopped[i] = True
                    print "Process {} stopped, pid == {}, average time == {}".format(i, processes[i].pid, times[i])
    
            # This code segment deletes the stopped processes from the dict
            # so we don't keep checking them (and know when to stop the main
            # program loop).
            for i in range(len(stopped)):
                if stopped[i] and processes.has_key(i):
                    del processes[i]
    
    
    if __name__ == '__main__':
        go()
    

    【讨论】:

    • poll 被写入“[s]et and return returncode 属性”。
    • 代码已编辑以反映上述见解;我一直认为您必须从返回码中提取值,因此感谢指针@eryksun。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2018-01-05
    • 1970-01-01
    • 2015-04-02
    相关资源
    最近更新 更多