从编译包中获得Python输出的最简单方法?

从编译包中获得Python输出的最简单方法?,python,python-2.7,Python,Python 2.7,先前信息:我在Mac电脑上 问:如果我使用py2app编译程序以进行重新分发,如何从程序执行中获得类似终端的文本输出 我的案例是一个复制大量大文件的程序,需要一段时间来处理,所以我希望每次复制每个文件时至少有一个输出通知 如果我在命令行上运行它,这很容易,我可以打印一个新行 但是,当我制作一个自给自足的包时,它只是在底部坞上打开,没有窗口,完成后关闭 一个简单的文本窗口就可以了 提前感谢。如果你想创建一个简单的文本窗口,你需要选择一个GUI框架来实现。对于这么简单的东西,没有理由不使用Tkint

先前信息:我在Mac电脑上

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

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

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

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

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


提前感谢。

如果你想创建一个简单的文本窗口,你需要选择一个GUI框架来实现。对于这么简单的东西,没有理由不使用
Tkinter
(任何Python都附带)或
PyObjC
(与苹果的Python 2.7一起预装),除非你碰巧更熟悉
wx
gobject
Qt
,等等

无论如何,您都需要编写一个函数来接收消息并将其附加到文本窗口(如果需要,可能会延迟创建),并在正常情况下打印时调用该函数。您可能还需要编写并安装一个执行相同操作的
logging
处理程序,以便只需
log.info
即可。(您可以创建一个类似文件的对象来执行此操作,并重定向
stdout
和/或
stderr
,但除非您无法控制
打印代码,否则这将是一项大量的工作。)

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

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

另一种方法是让代码与事件循环协同工作。有些库,如
wx
,具有类似
SafeYield
的函数,只要在每次处理后调用它,这些函数就可以工作。其他人没有,但是有一种从代码显式驱动事件循环的方法。其他人两者都没有,但每个事件循环框架都必须有一种安排新事件的方法,因此您可以将代码分解为一系列函数,每个函数都很快完成,然后执行类似于
root.after\u idle(nextfunc)
的操作


但是…你确定你需要这样做吗

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

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

或者您可以更简单:只需使用
日志记录
系统记录输出,如果您想查看每个文件何时完成,只需在
控制台.app中查看日志消息即可

最后,您是否首先需要
py2app
?如果没有任何外部依赖项,只需将脚本重命名为
Foo.command
,双击它即可在Terminal.app中运行它。如果您确实有外部依赖项,您可能仍然可以将其打包为一个文件夹,其中包含
.command
,而不是
.app


显然,这些想法都不是构建界面的专业或新手友好的方法,因此如果这很重要,您必须创建GUI。

谢谢。与此同时,我似乎找到了一个有趣的解决办法——鸭嘴兽。[链接]-它甚至为我提供了创建进度条的简单方法。如果我能用它,我想这将是我的解决方案!否则我会尝试你的建议。这不是很多工作,IIRC只需要做
sys.stdout=MyFancyObject
,而
MyFancyObject
有一个
write
方法。正如我在下面回应阿尔巴内特时所说的,与此同时,我似乎找到了一个有趣的解决方案——鸭嘴兽。[链接]-它甚至为我提供了创建进度条的简单方法。如果我能用它,我想这将是我的解决方案!否则我将尝试abarnert的建议。在大多数情况下,鸭嘴兽的工作原理与将
Foo.py
重命名为
Foo.command
的工作原理相同。特别是,如果您使用的是
py2app
,因为您有外部依赖关系等,那么Platypus将无法帮助您实现这一点。但是,如果除了“制作应用程序包”之外,你真的不需要py2app的任何功能,那么鸭嘴兽可能正是你想要的。