如果我可以完全独立地启动第二个程序,我会很高兴,就好像我只是“双击它”一样。
从 2.7 和 3.3 开始,Python 没有跨平台的方式来执行此操作。将来可能会添加新的shutil.open 方法(可能不在该名称下);有关详细信息,请参阅http://bugs.python.org/issue3177。但在那之前,您必须为您关心的每个平台编写自己的代码。
幸运的是,与 shutil.open 最终希望提供的相比,您尝试做的事情更简单,更不通用,这意味着编码并不难:
- 在 OS X 上,有一个名为
open 的命令完全符合您的要求:“打开命令打开文件(或目录或 URL),就像您双击文件的图标一样。”所以,你可以popenopen /Applications/MyGame.app。
- 在 Windows 上,等效命令是
start,但不幸的是,它是 cmd.exe shell 的一部分,而不是独立程序。幸运的是,Python 附带了一个函数 os.startfile,它可以做同样的事情,所以只需 os.startfile(r'C:\Program Files\MyGame\MyGame.exe')。
- 在与 FreeDesktop 兼容的 *nix 系统(包括大多数现代 linux 发行版等)上,有一个非常相似的命令,称为
xdg-open:“xdg-open 在用户首选应用程序中打开文件或 URL。”同样,只需popenxdg-open /usr/local/bin/mygame。
- 如果您希望在其他平台上运行,则需要进行一些研究以找到最佳的等价物。否则,对于 Mac 和 Windows 以外的任何东西,我都会尝试
popen xdg-open,如果失败则抛出错误。
请参阅http://pastebin.com/XVp46f7X 了解(未经测试的)示例。
请注意,这仅适用于运行实际上可以双击以在 Finder/Explorer/Nautilus/etc 中启动的内容。例如,如果您尝试启动“./script.py”,根据您的设置,它可能会启动一个包含您的脚本的文本编辑器。
此外,在 OS X 上,您希望运行 .app 包,而不是其中的 UNIX 可执行文件。 (在某些情况下,启动一个 UNIX 可执行文件——无论是在 .app 包中还是独立的——可能会起作用,但不要指望它。)
另外,请记住,以这种方式启动程序与从命令行运行程序不同 - 特别是,它将从 Windows/Launch Services/GNOME 继承其环境、当前目录/驱动器等/KDE/等。会话,而不是来自您的终端会话。如果您需要对子进程进行更多控制,则需要查看 open、xdg-open 和 os.startfile 的文档和/或提出不同的解决方案。
最后,仅仅因为open/xdg-open/os.startfile成功并不意味着游戏正常启动。例如,如果它在创建窗口之前启动然后崩溃,那么在您看来它仍然是成功的。
您可能想在 PyPI 中寻找可以满足您需求的库。 http://pypi.python.org/pypi/desktop 看起来很有可能。
或者您可以查看 issue 3177 中的补丁,然后选择您最喜欢的补丁。据我所知,它们都是纯 Python,您可以轻松地将添加的函数放到您自己的模块中,而不是 os 或 shutil。
作为一个快速破解,您可以(ab)使用webbrowser.open。 “请注意,在某些平台上,尝试使用此功能打开文件名可能会工作并启动操作系统的关联程序。但是,这既不支持也不可移植。”特别是 IIRC,它不适用于 OS X 10.5+。但是,我相信从文件名中创建一个 file: URL 实际上确实适用于 OS X 和 Windows,并且对于大多数(但不是全部)配置也适用于 linux。如果是这样,它对于快速和肮脏的脚本可能已经足够了。请记住,它没有被记录在案,它可能会为您的某些用户破坏,它可能会在将来破坏,并且它被 Python 开发人员明确认为是滥用,所以我不会指望它更严重。启动 'script.py' 或 'Foo.app/Contents/MacOS/foo'、传递 env 变量等也会遇到与上述更正确的方法相同的问题。
您问题中的几乎所有其他内容都是不相关且错误的:
通常不会有问题,但程序是游戏,并且内置了 Python 解释器。
没关系。如果游戏从 C 代码写入标准输出,它会做同样的事情。
当我使用 subprocess.Popen 时,它会启动单独的程序,但在原始程序的 Python 实例下这样做
不,它没有。它启动了一个全新的进程,其嵌入式 Python 解释器是一个全新的 Python 实例。您可以通过例如运行与游戏嵌入不同的 Python 版本来验证这一点。
以便他们共享第一个 Python 控制台。
不,他们没有。它们可能共享同一个 tty/cmd 窗口,但这不是一回事。
我可以很好地结束第一个程序,但我宁愿有单独的控制台(主要是因为我隐藏了控制台启动,但是当我使用 subprocess.POpen 从 Python 启动程序时它会显示)。
您始终可以通过管道将子进程的 stdout 和 stderr 传输到例如日志文件,然后您可以根据需要从父进程的输出中单独查看该日志文件。但我认为这与你真正关心的事情无关。
此外,os.system 将无法工作,因为我的目标是跨平台兼容性,而这仅适用于 Windows。
错了; os.system 在“Unix, Windows”上可用——这可能是你关心的任何地方。但是,它不起作用,因为它使用相同的 tty 在脚本的子 shell 中运行子程序。 (而且它还有很多其他问题——例如,阻塞直到孩子完成。)