我在SO上创建了一个基于另一个线程的简单服务器:Shutting down python TCPServer by custom handler
我使用像这样的pyinstaller将它包装成.exe:
pyinstaller C:\PATH TO FILE\server.py --distpath=\PATH TO FILE\ --onedir --onefile --noconsole
这在Windows上运行得非常好(目前在Win 7 x64上进行测试)。我可以将此exe文件复制到任何文件夹,并在该位置获取Web服务器。我是这样做的,因为我将它包装到一个将与另一个应用程序一起分发的进程中。这个应用程序的用户可能没有安装python,他们可能有一个浏览器阻止我想在申请过程中提供的东西。
这也适用于osx,但是当我尝试用pyinstaller包装相同的python脚本,而不是提供当前目录时,我在/ Users / Username位置得到一个服务器而不是app的目录跑了。
我在Win和OSX上工作的过程是从python shell开始并在那里运行脚本。这适用于两个平台。如果我使用终端,cd到我想要提供文件的目录,并从那里运行python脚本,一切正常。但是我将脚本包装成可执行文件的任何尝试都让我回到了/ Users / Username服务的相同结果,所以我显然缺少一些基本的包装工作方式。我假设它与shell脚本和脚本绑定到当前用户有关吗?
我想继续使用pyinstaller进行此过程,因为它在Windows和OSX上是相同的过程,但我似乎无法让生成的应用程序从运行它的目录中提供文件。任何有关正在发生的事情的指导,以及如何通过pyinstaller(或其他方法)修复它都将非常感激。
答案 0 :(得分:0)
@tallforasmurf on the pyinstaller Github指出我错过了pyinstaller docs中非常重要的内容:
适应“冻结”
在某些应用中,有必要在运行时了解应用是否正常运行 运行“直播”(来自源)或“冻结”(捆绑的一部分)。对于 例如,您可能有一个运行时的配置文件 “live”,基于模块的文件属性找到。那不会 捆绑代码时工作。
当您的应用程序需要访问数据文件时,例如a 配置文件或图标图像文件,您将获得该文件的路径 使用以下代码:
import sys import os ... if getattr(sys, 'frozen', False): # we are running in a |PyInstaller| bundle basedir = sys._MEIPASS else: # we are running in a normal Python environment basedir = os.path.dirname(__file__)
PyInstaller引导加载程序将冻结的属性添加到sys 模块。如果该属性存在,则您的脚本已由 引导程序。当这是真的时,sys._MEIPASS(注意下面的下划线) 名称)包含包含脚本和的文件夹的路径 与之捆绑的任何其他文件或文件夹。对于单文件夹模式 是分发文件夹。对于单文件模式,它是临时的 引导程序创建的文件夹。
当你的程序没有被引导程序启动时,标准 Python变量 file 是现在正在执行的脚本的完整路径, 和os.path.dirname()提取包含的文件夹的路径 它
在经过.app包目录的几个级别之后我能够os.chdir(basedir)
并正确地提供与.app包在同一目录中的文件。