这似乎是两个独立的问题。
首先,要在 Python 中直接运行可执行文件,您只需要 subprocess 模块即可。当你说你已经看过os.system 的文档时,我不知道你是怎么错过的,因为这清楚地表明:
subprocess 模块为生成新进程和检索其结果提供了更强大的工具;使用该模块优于使用此功能。请参阅subprocess 文档中的Replacing Older Functions with the subprocess Module 部分,了解一些有用的方法。
特别是,要在“lib/”文件夹中运行一些可执行文件,只需这样做:
p = subprocess.Popen(['lib/the_executable'])
但是,我猜你真的不希望当前工作目录中的lib,而是主脚本所在目录中的lib,对吧?为此,您需要在脚本启动时执行以下操作:
scriptdir = os.path.abspath(os.path.dirname(__file__))
…然后当你启动孩子时是这样的:
path = os.path.join(scriptdir, 'lib/the_executable')
p = subprocess.Popen([path])
无论如何,一旦你有一个Popen 对象,你可以检查p 是否仍在运行等,方法是每隔一段时间调用poll,或者通过产生一个线程来阻塞wait ;你可以通过调用kill来杀死它;等等。Popen objects 上的文档显示了您可以做的所有事情。
如果您希望运行启动 Python 可执行文件的 xterm 可执行文件,您可以这样做——只需将 xterm 作为第一个参数传递,并将相关的 xterm 参数作为其余参数传递.
但我看不出这对你有什么好处。您不是试图在窗口中嵌入终端会话,而是游戏本身。当您从 xterm 会话启动 GUI 应用程序时,它不会在 xterm 窗口内运行;它在新窗口中运行。如果嵌入了 xterm 窗口,也会发生同样的事情。
至于在自己的窗口中嵌入 Pygame 窗口,有两种方法。
如果您自己编写 Pygame 游戏,正如 display.init 文档所说:
在某些平台上,可以将 pygame 显示嵌入到已经存在的窗口中。为此,必须将环境变量 SDL_WINDOWID 设置为包含窗口 ID 或句柄的字符串。初始化 pygame 显示时会检查环境变量。请注意,在嵌入式显示器中运行时可能会出现许多奇怪的副作用。
注意Popen 构造函数采用env 参数:
如果env不是None,则必须是为新进程定义环境变量的映射;使用这些而不是继承当前进程的环境,这是默认行为。
所以,你可以这样做:
child_env = dict(os.environ)
child_env['SDL_WINDOWID'] = the_window_id
p = subprocess.Popen([path], env=child_env)
问题是,你给它什么窗口ID?好吧,您发布的博客已经有了答案。与 xterm 的-into 相同的 ID。
博客没有解释如何将其限制在窗口的部分,但它所引用的代码必须。答案是(a)在主窗口中嵌入一个子窗口,并将子窗口的 ID 提供给子进程,或者(b)将整个窗口提供给子进程,然后让子窗口立即创建一个子进程。表面并且只绘制到那个而不是整个显示。
但是,对于 Pygame(或其他 SDL)应用程序的特殊情况,与 xterm 不同,在环境中设置 SDL_VIDEO_WINDOW_POS 也应该有效。 (据我所知,这不是 Pygame 的文档功能,但它是 SDL 的文档功能,所以它应该是可靠的。)
最终,您可能需要在这两个应用程序之间进行一些合作。像这样的东西:
Tkinter 父母:
child_env = dict(os.environ)
child_env['SDL_WINDOWID'] = the_window_id
child_env['SDL_VIDEO_WINDOW_POS'] = '{},{}'.format(left, top)
p = subprocess.Popen([path, width, height], env=child_env)
Pygame 孩子:
width, height = sys.argv[1:3]
pygame.display.init()
pygame.display.set_mode((width, height), pygame.NOFRAME)
如果您无法修改 Pygame 应用程序,事情就会变得更加棘手。您将必须创建嵌入到父窗口中的两个单独的窗口,或者以某种方式将两个顶级窗口停靠在一起。 (后者并不像在 X11 中听起来那么可怕。每当一个窗口移动时,以编程方式移动另一个窗口。)无论哪种方式,您都可以启动嵌入在一个子窗口中的 Pygame 应用程序,并将 Tkinter 的东西塞进另一个窗口。你也许可以通过 Tkinter 做到这一点;您可能必须直接进行 Xlib 调用(通过 ctypes-ing 到 Xlib,或使用类似 python-xlib 的方法)。