从 Python 启动另一个程序 >单独 < [英] Start Another Program From Python >Separately<

查看:22
本文介绍了从 Python 启动另一个程序 >单独 <的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试运行一个外部的、独立于 Python 的程序.通常不会有问题,但该程序是一个游戏,并且内置了 Python 解释器.当我使用 subprocess.Popen 时,它会启动单独的程序,但会在原始程序的 Python 实例下启动,以便它们共享第一个 Python 控制台.我可以很好地结束第一个程序,但我宁愿有单独的控制台(主要是因为我隐藏了控制台开始,但是当我使用 subprocess.POpen 从 Python 启动程序时它会显示出来).

I'm trying to run an external, separate program from Python. It wouldn't be a problem normally, but the program is a game, and has a Python interpreter built into it. When I use subprocess.Popen, it starts the separate program, but does so under the original program's Python instance, so that they share the first Python console. I can end the first program fine, but I would rather have separate consoles (mainly because I have the console start off hidden, but it gets shown when I start the program from Python with subprocess.POpen).

如果我可以完全独立启动第二个程序,我会很高兴,就像我只是双击它"一样.此外,os.system 将无法工作,因为我的目标是跨平台兼容性,而这仅适用于 Windows.

I would like it if I could start the second program wholly on its own, as though I just 'double-clicked on it'. Also, os.system won't work because I'm aiming for cross-platform compatibility, and that's only available on Windows.

推荐答案

如果我可以完全独立启动第二个程序,我会很高兴,就像我只是双击它"一样.

I would like it if I could start the second program wholly on its own, as though I just 'double-clicked on it'.

从 2.7 和 3.3 开始,Python 没有跨平台的方式来做到这一点.将来可能会添加一个新的 shutil.open 方法(可能不在该名称下);有关详细信息,请参阅 http://bugs.python.org/issue3177.但在那之前,您必须为您关心的每个平台编写自己的代码.

As of 2.7 and 3.3, Python doesn't have a cross-platform way to do this. A new shutil.open method may be added in the future (possibly not under that name); see http://bugs.python.org/issue3177 for details. But until then, you'll have to write your own code for each platform you care about.

幸运的是,您尝试做的事情比 shutil.open 最终希望提供的更简单、更通用,这意味着编码并不难:

Fortunately, what you're trying to do is simpler and less general than what shutil.open is ultimately hoped to provide, which means it's not that hard to code:

  • 在 OS X 上,有一个命令叫做 open 完全符合您的要求:open 命令打开一个文件(或目录或 URL),就像您双击文件的图标一样."因此,您只需popen 打开/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."同样,只需 popen xdg-open/usr/local/bin/mygame.
  • 如果您希望在其他平台上运行,则需要进行一些研究以找到最佳的等价物.否则,对于 Mac 和 Windows 以外的任何东西,我只会尝试 popen xdg-open,如果失败则抛出错误.
  • On OS X, there's a command called open that does exactly what you want: "The open command opens a file (or a directory or URL), just as if you had double-clicked the file's icon." So, you can just popen open /Applications/MyGame.app.
  • On Windows, the equivalent command is start, but unfortunately, that's part of the cmd.exe shell rather than a standalone program. Fortunately, Python comes with a function os.startfile that does the same thing, so just os.startfile(r'C:\Program Files\MyGame\MyGame.exe').
  • On FreeDesktop-compatible *nix systems (which includes most modern linux distros, etc.), there's a very similar command called xdg-open: "xdg-open opens a file or URL in the user's preferred application." Again, just popen xdg-open /usr/local/bin/mygame.
  • If you expect to run on other platforms, you'll need to do a bit of research to find the best equivalent. Otherwise, for anything besides Mac and Windows, I'd just try to popen xdg-open, and throw an error if that fails.

有关(未经测试的)示例,请参阅 http://pastebin.com/XVp46f7X.

See http://pastebin.com/XVp46f7X for an (untested) example.

请注意,这仅适用于运行实际上可以在 Finder/Explorer/Nautilus/等中双击启动的内容.例如,如果您尝试启动./script.py",根据您的设置,它可能会启动包含您的脚本的文本编辑器.

Note that this will only work to run something that actually can be double-clicked to launch in Finder/Explorer/Nautilus/etc. For example, if you try to launch './script.py', depending on your settings, it may just fire up a text editor with your script in it.

此外,在 OS X 上,您希望运行 .app 包,而不是其中的 UNIX 可执行文件.(在某些情况下,启动 UNIX 可执行文件——无论是在 .app 包内还是独立的——可能会起作用,但不要指望它.)

Also, on OS X, you want to run the .app bundle, not the UNIX executable inside it. (In some cases, launching a UNIX executable—whether inside an .app bundle or standalone—may work, but don't count on it.)

另外,请记住,以这种方式启动程序与从命令行运行程序不同——特别是,它将从 Windows/Launch Services/GNOME 继承其环境、当前目录/驱动器等/KDE/等.会话,而不是来自您的终端会话.如果您需要对子进程进行更多控制,则需要查看 openxdg-openos.startfile 的文档和/或提出不同的解决方案.

Also, keep in mind that launching a program this way is not the same as running it from the command line—in particular, it will inherit its environment, current directory/drive, etc. from the Windows/Launch Services/GNOME/KDE/etc. session, not from your terminal session. If you need more control over the child process, you will need to look at the documentation for open, xdg-open, and os.startfile and/or come up with a different solution.

最后,仅仅因为 open/xdg-open/os.startfile 成功并不意味着游戏正常启动.例如,如果它在创建窗口之前启动然后崩溃,在您看来它仍然是成功的.

Finally, just because open/xdg-open/os.startfile succeeds doesn't actually mean that the game started up properly. For example, if it launches and then crashes before it can even create a window, it'll still look like success to you.

您可能想在 PyPI 中寻找可以执行您想要的操作的库.http://pypi.python.org/pypi/desktop 看起来很有可能.

You may want to look around PyPI for libraries that do what you want. http://pypi.python.org/pypi/desktop looks like a possibility.

或者您可以查看 issue 3177 中的补丁,然后选择您最喜欢的补丁.据我所知,它们都是纯 Python,您可以轻松地将添加的函数放在自己的模块中,而不是在 osshutil 中.

Or you could look through the patches in issue 3177, and pick the one you like best. As far as I know, they're all pure Python, and you can easily just drop the added function in your own module instead of in os or shutil.

作为一个快速的 hack,你可以(ab)使用 webbrowser.open.请注意,在某些平台上,尝试使用此功能打开文件名可能会起作用并启动操作系统的关联程序.但是,这既不支持也不可移植."特别是 IIRC,它不适用于 OS X 10.5+.但是,我相信从文件名中创建一个 file: URL 实际上确实适用于 OS X 和 Windows,并且也适用于大多数(但不是全部)配置的 linux.如果是这样,它可能足以用于快速而肮脏的脚本.请记住,它没有被记录在案,它可能会损坏您的某些用户,将来可能会损坏,并且它被 Python 开发人员明确认为是滥用,所以我不会指望它会更严重.并且在启动script.py"或Foo.app/Contents/MacOS/foo"、传递环境变量等时会遇到与上面更正确的方法相同的问题.

As a quick hack, you may be able to (ab)use webbrowser.open. "Note that on some platforms, trying to open a filename using this function, may work and start the operating system’s associated program. However, this is neither supported nor portable." In particular, IIRC, it will not work on OS X 10.5+. However, I believe that making a file: URL out of the filename actually does work on OS X and Windows, and also works on linux for most, but not all, configurations. If so, it may be good enough for a quick&dirty script. Just keep in mind that it's not documented to work, it may break for some of your users, it may break in the future, and it's explicitly considered abuse by the Python developers, so I wouldn't count on it for anything more serious. And it will have the same problems launching 'script.py' or 'Foo.app/Contents/MacOS/foo', passing env variables, etc. as the more correct method above.

您问题中的几乎所有其他内容都是不相关且错误的:

Almost everything else in your question is both irrelevant and wrong:

通常不会有问题,但该程序是一个游戏,并且内置了 Python 解释器.

It wouldn't be a problem normally, but the program is a game, and has a Python interpreter built into it.

没关系.如果游戏从 C 代码写入标准输出,它会做完全相同的事情.

That doesn't matter. If the game were writing to stdout from C code, it would do the exact same thing.

当我使用 subprocess.Popen 时,它会启动单独的程序,但会在原始程序的 Python 实例下启动

When I use subprocess.Popen, it starts the separate program, but does so under the original program's Python instance

不,不是.它启动了一个全新的进程,其嵌入式 Python 解释器是一个全新的 Python 实例.例如,您可以通过运行与游戏嵌入的不同版本的 Python 来验证这一点.

No it doesn't. It starts an entirely new process, whose embedded Python interpreter is an entirely new instance of Python. You can verify that by, e.g., running a different version of Python than the game embeds.

以便他们共享第一个 Python 控制台.

so that they share the first Python console.

不,他们没有.它们可能共享同一个 tty/cmd 窗口,但这不是一回事.

No they don't. They may share the same tty/cmd window, but that's not the same thing.

我可以很好地结束第一个程序,但我宁愿有单独的控制台(主要是因为我隐藏了控制台开始,但是当我使用 subprocess.POpen 从 Python 启动程序时它会显示出来).

I can end the first program fine, but I would rather have separate consoles (mainly because I have the console start off hidden, but it gets shown when I start the program from Python with subprocess.POpen).

您始终可以将子进程的 stdout 和 stderr 通过管道传输到例如日志文件,然后您可以根据需要将其与父进程的输出分开查看.但我认为这与您真正关心的事情无关.

You could always pipe the child's stdout and stderr to, e.g., a logfile, which you could then view separately from the parent process's output, if you wanted to. But I think this is going off on a tangent that has nothing to do with what you actually care about.

此外,os.system 将无法工作,因为我的目标是跨平台兼容性,而这仅适用于 Windows.

Also, os.system won't work because I'm aiming for cross-platform compatibility, and that's only available on Windows.

错误;os.system 在Unix"上可用, Windows"——这可能是您关心的任何地方.但是,它不起作用,因为它使用相同的 tty 在脚本的子 shell 中运行子程序.(而且它还有很多其他问题——例如,阻塞直到孩子完成.)

Wrong; os.system is available on "Unix, Windows"--which is probably everywhere you care about. However, it won't work because it runs the child program in a subshell of your script, using the same tty. (And it's got lots of other problems—e.g., blocking until the child finishes.)

这篇关于从 Python 启动另一个程序 >单独 <的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆