和subprocess.run()相比而言,subprocess.popen是一个更底层的接口,它具有非常高的灵活性,能够处理一些不太常见的情况。使用subprocess.Popen()会在新进程中执行子程序。在POSIX上,该类使用os.execvp()的类似行为来执行子程序。在Windows上,该类使用Windows CreateProcess() 函数。
subprocess.Popen( args, bufsize=-1, executable=None, stdin=None, stdout=None, stderr=None, preexec_fn=None, close_fds=True, shell=False,
cwd=None, env=None, universal_newlines=False, startupinfo=None, creationflags=0, restore_signals=True, start_new_session=False, pass_fds=())
args,
bufsize=-1,
(仅当universal_newlines = True时才可用,即在文本模式下), 其它正值表示使用的缓冲区的大小,负值表示使用系统默认的io.DEFAULT_BUFFER_SIZE。
executable=None,
程序。大多程序将args作为命令的名称,这与真正执行的命令不同。
stdin=None,
stdout=None,
stderr=None,
preexec_fn=None,
close_fds=True,
shell=False,
认是/ bin / sh。 如果args是一个字符串,则该字符串指定要通过shell执行的命令。 这意味着字符串的格式必须与在shell提示符下键入时完全相
同。例如,引用或反斜杠转义带有空格的文件名。 如果args是一个序列,则第一个项指定命令字符串,并且任何其他项将被视为shell本身的附加参
数。 等价于 Popen(['/bin/sh', '-c', args[0], args[1], ...])
cwd=None,
env=None,
universal_newlines=False,
startupinfo=None,
creationflags=0,
restore_signals=True,
start_new_session=False,
pass_fds=()
通过with语句支持Popen对象作为上下文管理器:退出时,将关闭标准文件描述符,并等待进程。
with Popen(["ifconfig"], stdout=PIPE) as proc:
log.write(proc.stdout.read())
Popen类有如下这些实例方法:
Popen.poll()
Popen.wait(timeout=None)
Popen.communicate(input=None, timeout=None)
proc = subprocess.Popen(...)
try:
outs, errs = proc.communicate(timeout=15)
except TimeoutExpired:
proc.kill()
outs, errs = proc.communicate()
Popen.send_signal(signal)
Popen.terminate()
Popen.kill()
Popen.args
Popen.stdin
Popen.stdout
Popen.stderr
Popen.pid
Popen.returncode
import os
import sys
import time
import datetime
import psutil
import subprocess
TIME = 1
CMD = "test.py"
class MyDeamon(object):
def __init__(self, sleep_time, cmd):
self.sleep_time = sleep_time
self.cmd = cmd
self.p = None
self.run()
def check(self):
try:
while True:
time.sleep(self.sleep_time * 60)
self.pid = self.p.pid
self.poll = self.p.poll()
if self.poll:
print("程序已终止,重启程序")
self.p.kill()
self.run()
else:
print("[{}] 程序正在运行中".format(datetime.datetime.now()))
except KeyboardInterrupt as e:
print("[{}] 监测到ctrl+c,准备退出程序".format(datetime.datetime.now()))
self.p.kill()
def run(self):
if self.cmd.endwith('.py'):
print("[{}] 开始运行子进程!".format(datetime.datetime.now()))
self.p = subprocess.Popen(['python3', '{}'.format(self.cmd)], stdin=sys.stdin, stdout=sys.stdout, stderr=sys.stderr,shell=False)
else:
print("{}] 请运行py文件!".format(datetime.datetime.now()))
if __name__ == '__main__':
app = MyDeamon(TIME, CMD)
app.check()
[1] subprocess官方文档
[2] python的subprocess模块
目录1. 简单介绍1.1. psutil1.2. subprocess1.2.1. subprocess.run()subprocess.CompletedProcess可能会用到的一些值1.2.3. subprocess.Popen4. 代码实例5. 参考文献1. 简单介绍通过使用python中的psutil库和subprocess库,实现了一个守护进程。1.1. psutil1.2. ...
1.1 守护进程
守护进程是系统中生存期较长的一种进程,常常在系统引导装入时启动,在系统关闭时终止,没有控制终端,在后台运行。守护进程脱离于终端是为了避免进程在执行过程中的信息在任何终端上显示并且进程也不会被任何终端所产生的终端信息所打断。
在这里,我们在Linux2.6内核的centos中,ps -ef |awk '{print $1"\t "$2"\t "$3"
进程是资源分配的最小单位,线程是CPU调度的最小单位。
每一个进程启动时都会最先产生一个线程,即主线程。然后主线程会再创建其他的子线程。
与进程相关的资源包括:内存页(同一个进程中的所有线程共享同一个内存空间);文件描述符(e.g. open sockets);安全凭证(e.g.启动该进程的用户ID)
GIL(Global Interpreter Lock,全局解释器锁)
在非python环境中,单核情况下,同时只能有一个任务执行。多核时可以支持多个线程同时执行。但是在python中,无论有多少核,同时.
参考文章:https://www.cnblogs.com/lincappu/category/1140217.html
1.1 线程、多线程
线程是一个基本的 CPU 执行单元。它必须依托于进程存活。一个线程是一个execution context(执行上下文),即一个 CPU 执行时所需要的一串指令。
多线程共享同个地址空间、打开的文件以及其他资源。
线程的类型:主线程、子线程、...
运行并等待args参数指定的指令完成,返回CompletedProcess实例。
参数:(*popenargs, input=None, capture_output=False, timeout=None, check=False, **kwargs)。除input, capture_output, timeout, check,其他参数与Popen构造器参数一致。
capture_output:如果设置为True,表示重定向stdout和stderr到管道,且不能
5. python实现多进程
Unix/Linux操作系统提供了一个fork()系统调用,它非常特殊。普通的函数调用,调用一次返回一次,但是fork()调用一次返回两次,因为操作系统自动把当前进程(称为父进程)复制了一份(称为子进程),然后分别在父进程和子进程内返回。
子进程永远返回0,而父进程返回进程的ID。一个父进程可以fork出多个子进程,所以父进程要记下每个子进程的ID,而子进程只主要调用getppid()就可以拿到父进程的ID。
父进程、子进程执行的顺序没有规律,完全取决于操作系统的调度
# 执行命令
p = subprocess.Popen(['python'], stdin=subprocess.PIPE, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
# 与用户交互
while True:
# 获取用户输入
user_input = input('> ')
# 将用户输入发送给子进程
p.stdin.write(user_input.encode())
p.stdin.write(b'\n')
p.stdin.flush()
# 从子进程获取输出
output = p.stdout.readline().decode().strip()
# 输出子进程的响应
print(output)
这个代码会启动一个Python子进程,并与用户交互。用户可以输入任何Python代码,子进程会执行并返回结果。