从编译包中获取Python输出的最简单方法是什么?

时间:2013-02-06 19:01:39

标签: python python-2.7

事先信息:我在Mac上。

问:如果我使用py2app进行编译以进行重新分发,如何从程序执行中获得类似终端的文本输出?

我的案例是一个复制很多大文件的程序,需要一段时间来处理,所以每次复制每个文件时我都希望至少有一个输出通知。

如果我在命令行上运行它很容易,我可以打印一个新行。

但是当我制作一个自给自足的包装时,它只是在底部的底座上打开,没有窗户,并在完成后关闭。

一个简单的文本窗口就可以了。

提前致谢。

1 个答案:

答案 0 :(得分:0)

如果要创建一个简单的文本窗口,则需要选择一个GUI框架来实现。对于这么简单的事情,没有理由不使用Tkinter(随任何Python附带)或PyObjC(预先安装Apple的Python 2.7),除非您恰好对wxgobjectQt等更熟悉。

无论如何,无论如何,你都需要编写一个接收消息并将其附加到文本窗口的函数(如果需要可能会懒得创建它),并在任何地方调用该函数通常是print。您可能还想编写并安装执行相同操作的logging处理程序,因此您只需log.info个东西。 (您可以而是创建一个类似文件的对象来执行此操作并重定向stdout和/或stderr,但除非您无法控制print代码,这将会有更多的工作。)

这里唯一真正的问题是GUI需要一个事件循环,您可能只是将代码编写为顺序脚本。

另一种方法是将整个当前脚本转换为后台线程。如果您正在使用允许您从后台线程访问小部件的GUI库,那么一切都很简单;您的printfunc只是textwidget.append(msg)。如果没有,它可能至少具有call_on_main_thread类型功能,因此printfunc执行call_on_main_thread(textwidget.append, msg)。如果最坏的情况发生(我相信Tkinter会这样做),你必须创建一个显式队列来推送消息,并在事件循环中编写一个队列处理程序。 This recipe应该给你一个想法。将workerThread的正文替换为您的代码,并以self.endApplication()结尾。 (可能有更好的例子;这正是我在快速搜索中首先发现的。)

另一种方法是让你的代码与事件循环协同工作。有些库,比如wx,有像SafeYield这样的函数,只要你在每一块处理后调用它就能使它工作。其他人没有,但有办法从代码中明确驱动事件循环。其他人没有 - 但每个事件循环框架都必须有一种方法来安排新事件,因此您可以将代码分解为一系列函数,每个函数都快速完成,然后执行类似root.after_idle(nextfunc)的操作。


但是......你确定你需要这样做吗?

首先,任何应用程序(包括由py2app创建的应用程序)如果您使用Foo.app/Contents/MacOS/Foo运行它,都会将其stdout发送到终端。如果你愿意,你甚至可以设置open Foo.app以这种方式工作。显然这对于​​只在Finder中双击应用程序的人来说没有任何帮助(因为那时 没有终端),但有时只需要输出可用就足够了人们需要它并知道如何遵循指示。

您可以更进一步:创建一个Foo.command文件,只执行类似$(dirname $0)/Foo.app/Contents/MacOS/Foo的操作,当您双击该文件时,它会启动Terminal.app并运行您的脚本。

或者您可以更简单:只需使用logging来syslog输出,如果您想查看每个文件何时完成,只需在Console.app中查看日志消息。

最后,您首先需要py2app吗?如果您没有任何外部依赖项,只需将脚本重命名为Foo.command,然后双击它将在Terminal.app中运行它。如果具有外部依赖关系,您仍然可以将它们全部捆绑在一起作为其中包含.command而不是.app的文件夹。< / p>

显然,这些想法都不是构建界面的专业或新手友好方式,所以如果这很重要,你将不得不创建一个GUI。