在 Windows 操作系统上,您想运行一个 .bat 文件,并希望该文件始终在后台运行,以便可以在继续执行其他任务的同时运行该文件。您认为创建一个新进程是您唯一的选择。您希望代码执行类似以下操作:
def startSim:
# open .bat file in a new window
os.system("startsim.bat")
# continue doing other stuff here
print("Simulator started")
您使用的是 Windows 操作系统,因此无法使用 os.fork。
2. 解决方案
方法一:使用 subprocess.Popen
import subprocess
def startSim():
child_process = subprocess.Popen("startsim.bat")
# Do your stuff here.
# You can terminate the child process after done.
child_process.terminate()
# You may want to give it some time to terminate before killing it.
time.sleep(1)
if child_process.returncode is None:
# It has not terminated. Kill it.
child_process.kill()
方法二:使用 os.startfile
import os
def startSim():
os.startfile("startsim.bat")
# Do your stuff here.
方法三:使用 os.spawn
import os
import string
if os.name in ("nt", "dos"):
exefile = ".exe"
else:
exefile = ""
def spawn(program, *args):
try:
# check if the os module provides a shortcut
return os.spawnvp(program, (program,) + args)
except AttributeError:
pass
try:
spawnv = os.spawnv
except AttributeError:
# assume it's unix
pid = os.fork()
if not pid:
os.execvp(program, (program,) + args)
return os.wait()[0]
else:
# got spawnv but no spawnp: go look for an executable
for path in string.split(os.environ["PATH"], os.pathsep):
file = os.path.join(path, program) + exefile
try:
return spawnv(os.P_WAIT, file, (file,) + args)
except os.error:
pass
raise IOError, "cannot find executable"
#
# try it out!
spawn("python", "hello.py")
print "goodbye"
方法四:使用 subprocess.Popen 和管道
import subprocess
proc = subprocess.Popen(['/path/script.bat'],
stdout=subprocess.PIPE,
stderr=subprocess.STDOUT)
方法五:创建 Windows 服务
您可以使用 Windows 服务来实现后台运行。
import win32serviceutil
import win32service
import win32event
class PythonService(win32serviceutil.ServiceFramework):
_svc_name_ = "PythonService"
_svc_display_name_ = "Python Service"
def __init__(self, args):
win32serviceutil.ServiceFramework.__init__(self, args)
self.hWaitStop = win32event.CreateEvent(None, 0, 0, None)
def SvcStop(self):
self.ReportServiceStatus(win32service.SERVICE_STOP_PENDING)
win32event.SetEvent(self.hWaitStop)
def SvcDoRun(self):
while True:
rc = win32event.WaitForSingleObject(self.hWaitStop, 100)
if rc == win32event.WAIT_OBJECT_0:
break
if __name__ == '__main__':
win32serviceutil.HandleCommandLine(PythonService)
备注
- 方法一和方法二都使用 Python 的 subprocess 模块来运行 .bat 文件,但方法一使用
subprocess.Popen()
函数创建子进程,而方法二使用os.startfile()
函数启动文件。 - 方法三使用
os.spawn()
函数创建子进程,该函数是 Windows 操作系统独有的。 - 方法四使用
subprocess.Popen()
函数创建子进程,并使用管道来捕获子进程的输出。 - 方法五使用 Windows 服务来实现后台运行,这是一种更可靠的方式,但需要更多的代码和配置。