利用内建的 subprocess 模块中的 Popen() 函数,Python 程序可以启动计算机中的其他程序( Popen() 函数名中的P 表示 process ,进程)。如果你打开了一个应用程序 的多个实例,每个实例都是同一个程序的不同进程。例如, 如果你同时打开了Web浏览器的多个窗口,每个窗口都是 Web 浏览器程序的不同进程。
每个进程可以有多个线程。不像线程,进程无法直接读写另一个进程的变量。 如果你认为多线程程序是多个手指在追踪源代码,那么同一个程序 打开多个进程就像有一个朋友拿着程序源代码的独立副本。 你们都独立地执行相同的程序。
如果想在 Python 脚本中启动一个外部程序,就将该程序的文件名传递给 subprocess.Popen() (在Windows 中,右键点击该应用程序的开始 菜单项,然后选择“属性”,查看应用程序的文件名。在 OS X 上, 按住 Ctrl 键单击该应用程序并选择
“显示包内容”,找到可执行文件的路径)。Popen()函数随后将立即返回。 请记住,启动的程序和你的Python程序不在同一线程中运行。
在Windows计算机上,在交互式环境中输入以下代码:
import subprocess
subprocess.Popen( ‘C:\Windows\System32\calc.exe’)
在 UbuntuLinux 上,可以输入以下代码:
import subprocess
subprocess.Popen(‘/usr/bin/gnome-calculator’)
在 OS X 上,过程稍有不同。参见15.8.5节“用默认应用程序打开文件”。 返回值是一个 Popen 对象,它有两个有用的方法: poll() 和wait() 。
可以认为 poll() 方法是问你的朋友,她是否执行完毕 你给她的代码。如果这个进程在 poll() 调用时仍在运行, poll() 方法就返回None 。如果该程序已经终止, 它会返回该进程的整数退出代码。退出代码用于说明进程是 无错终止(退出代码为0),还是一个错误导致进程终止 (退出代码非零,通常为1,但可能根据程序而不同)。
wait()方法就像是等着你的朋友执行完她的代码,然后你 继续执行你的代码。 wait()方法将阻塞,直到启动的进程终止。 如果你希望你的程序暂停,直到用户完成与其他程序,这非常有用。 wait()的返回值是进程的整数退出代码。
在Windows上,在交互环境中输入以下代码。请注意, wait() 的调用将阻塞,直到退出启动的计算器程序。
calcProc =subprocess.Popen(‘c:\Windows\System32\calc.exe’)
calcProc.poll() == None
calcProc.wait()
calcProc.poll()
这里,我们打开了计算器程序。在它仍在运行时,我们检查 polio 是否返回None 。它应该返回 None, 因为该进程仍在运行。然后,我们关闭计算器程序,并对 已终止的进程调用wait()。wait() 和poll() 现在返回0,说明该进程终止且无错。
用Popen()创建进程时,可以向进程传递命令行参数。 要做到这一点,向Popen()传递一个列表,作为唯一的参数。 该列表中的第一个字符串是要启动的程序的可执 行文件名,所有后续的字符串将是该程序启动时, 传递给该程序的命令行参数。实际上,这个列表将 作为被启动程序的sys.argv的值。
大多数具有图形用户界面(GUI)的应用程序, 不像基于命令行或基于终端的程序那样尽可能地使用命令行 参数。但大多数 GUI 应用程序将接受一个参数,表示 应用程序启动时立即打开的文件。例如,如果你使用的是 Windows,创建一个简单的文本文件 C:hello.txt , 然后在交互式环境中输入以下代码:
subprocess.Popen( [‘C:\Windows\notepad.exe’,‘C:\hello.txt’])
这不仅会启动记事本应用程序, 也会让它立即打开 C:hello.txt 。
如果你精通计算机,可能知道Windows上的 Task Scheduler,OS X 上的launchd, 或 Linux 上的 cron 调度程序。这些工具文档齐全, 而且可靠,它们都允许你安排应用程序在特定的时间启动。 如果想更多地了解它们,http://nostarch.com/automatestuff/ 找到教程的链接。
利用操作系统内置的调度程序,你不必自己写时钟检查代码 来安排你的程序。但是,如果只需要程序稍作停顿,就用 time.sleep() 函数。或者不使用操作系统的调度程序, 代码可以循环直到特定的日期和时间,每次循环时调用 time.sleep(1)。
webbrowser.open() 函数可以从程序启动 Web 浏览器, 打开指定的网站,而不是用 subprocess.Popen() 打开 浏览器应用程序。
可以在Python中启动另一个Python脚本,就像任何其他的 应用程序一样。只需向 Popen() 传入python.exe 可执行文件,并将想运行的. py 脚本的文件名作为它的参 数。例如,下面代码将运行第1章的 hello.py 脚本:
subprocess.Popen( [‘C:\python34\python.exe’, ‘hello.py’])
向 Popen() 传入一个列表,其中包含 Python 可执行 文件的路径字符串,以及脚本文件名的字符串。如果要启动的 脚本需要命令行参数,就将它们添加列表中,放在脚本文件名 后面。在 Windows 上, Python 可执行文件的路径是 C:\python34\python.exe 。 在OS X上, 是/Library/Frameworks/Python.framework/Versions/3.3/bin/python3。 在Linux上,是/usr/bin/python3。
不同于将Python程序导入为一个模块,如果Python程序 启动了另一个Python程序,两者将在独立的进程中运行, 不能分享彼此的变量。
双击计算机上的 .txt 文件,会自动启动与 .txt 文件扩展名 关联的应用程序。计算机上已经设置了一些这样的文件扩展名 关联。利用 Popen(),Python也可以用这种方式打开文件。
每个操作系统都有一个程序,其行为等价于双击文档文件来 打开它。在Windows上,这是 start 程序。在OS X上, 这是 open 程序。在 Ubuntu Linux 上,这是 see 程序。 在交互式环境中输入以下代码,根据操作系统,向 Popen() 传入’start’、‘open’ 或’see’ :
fileObj = open(‘hello.txt’, ‘w’)
fileObj .write(‘Hello world!’)
fileObj.close()
import subprocess
subprocess.Popen([‘start’, ‘hello.txt’], shell=True)
这里,我们将Hello world!写入一个新的hello.txt文件。 然后调用Popen(),传入一个列表,其中包含程序名称(在这个 例子中,是Windows上的’start’),以及文件名。我们也 传入了shelHTme关键字参数,这只在Windows上需要。 操作系统知道所有的文件关联,能弄清楚应该启动哪个程序, 比如Notepad.exe,来处理hello.txt文件。
在OS X上,open程序用于打开文档文件和程序。 如果你有Mac,在交互式环境中输入以下代码:
subprocess.Popen([‘open’,‘/Applications/Calculator.app/’])
计算器应用程序应该会打开。