我尝试使用PyInstaller


我尝试使用PyInstaller,它可以立即将Python脚本转换为Windows的可执行文件。
我偶然发现了各种各样的东西,因此在忘记之前我会写一份备忘录。

如何自行安装PyInstaller

目前,以下内容。

命令

1
  $ pip install pyinstaller

如果您在项目中使用pipenv,则位于下方(出于某些原因,我在下方写道)

命令

1
  $ pipenv install -d pyinstaller

遇到的问题和对策

编译跨越多个文件的项目时,我应该针对哪个文件?

指定将作为入口点的文件(例如具有main的文件)作为参数。 PyInstaller将在未经许可的情况下分析剩余的依赖项

不知何故,许多警告出现在日志

它似乎与Visual C的开发模块有关,但是您暂时可以忽略它

看起来像Windows 10 Universal C Runtime 1

即使您暂时没有它,它似乎也可以工作,但是如果您很好奇,请将文件夹c:\windows\WinSxS\x86_microsoft-windows-m..namespace-downlevel_***(環境ごとに異なる文字)添加到参考路径中,它将消失。

但是,在我的环境中,只有错误WARNING: lib not found: api-ms-win-core-file-l2-1-0.dll dependency of c:\...\ucrtbase.dll没有消失。

我想将其用于商业目的

PyInstaller似乎可以用于商业用途。 2

__file__不再指向正确的值。

让我们使用

sys.argv [0]。但是,"父文件夹路径"可能与预期的路径不同,例如,将文件放置在" [项目名称] \\ src"下并根据常规配置进行开发时,请格外小心。
最好根据Path#后缀是否为exe来划分进程。

实施实例

1
2
3
4
5
  def mypath():
    import sys
    from pathlib import Path
    p = Path(sys.argv[0])
    return p if p.suffix == ".exe" else p.parent

另外,似乎您也可以使用hasattr(sys, "frozen")(在exe时为真)检查PyInstaller是否已执行(可执行文件) 3

2018/10/19后记:使用unittest

当使用Python的标准测试框架unittest时,我已经确认了使用上述实现执行单元测试时无法获得正确路径的问题。
因此,编写以下内容可能是安全的:

实施实例

1
2
3
4
5
  def mypath():
    import sys
    from pathlib import Path
    return Path(sys.argv[0]) if hasattr(sys, "frozen") else \
      Path(__file__).parent

使用pipenv时为

我最上瘾了。当我照常从控制台调用pyinstaller时,exe照常输出,但导入的库未加载。

在pipenv的Github上有一个关于此区域的问题,但是 4,而不是使用pip命令在全局安装PyInstaller的系统,而是将PyInstaller放入使用pipenv创建的虚拟环境中它。

因此,请使用pipenv命令安装pyinstaller,并确保从执行pipenv shell的环境中调用PyInstaller。

命令

1
2
3
  $ pipenv install -d pyinstaller
  $ pipenv shell
  $ pyinstaller ...

如果导入的库使用Python

以外的库

主要是DLL等您可以通过运行编译的exe文件并在需要DLL时获取异常来看到此信息(跟踪显示需要的DLL以及应将其存储在何处)。
库使用的DLL通常位于已安装模块的site-packages文件夹中,因此请使用PyInstaller参数--add-binary将其包括在可执行文件中。 5

我想在其他地方使用内容输出到标准输出

例如,如果要将以前在CUI上显示的文字输出到GUI或用作日志(例如带有GUI的应用程序),请在输出之前编写以下代码。

附加代码

1
2
  import sys
  sys.stdout = open("file.log", "w")

当输出到

GUI时,似乎可以通过将实现write方法的对象插入sys.stdout暂时进行重定向。我还没有做,因为这很麻烦(也许我会尽快做) 6

另外,如果要舍弃标准输出,请使用os.devnull。

附加代码

1
2
3
  import sys
  import os
  sys.stdout = open(os.devnull, "w")

基于以上内容,编写代码进行编译

我认为这将是一个反复试验的过程,因此编写批处理文件或其他文件肯定更容易。看来您可以使用主要输出的spec文件,但是我不

create_exe.ps1

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
if (Test-Path dist) {
  Remove-Item dist -Recurse | Out-Null
}
New-Item dist -ItemType Directory | Out-Null
$windll = "c:\windows\WinSxS\x86_microsoft-windows-m..namespace-downlevel_*"
$windllpath = "."
if(Test-Path $windll){
  $item = (Get-ChildItem $windll | Sort-Object LastWriteTime)[0]
  $windllpath = '"c:\windows\WinSxS\{0}"' -f $item.Name
}
pyinstaller `
  --onefile `
  --name Application `
  --path $windllpath `
  --specpath ./dist/ `
  --distpath ./dist/dist `
  --workpath ./dist/build `
  --add-binary "../.venv/Lib/site-packages/pyzbar/libzbar-32.dll;pyzbar/" `
  --add-binary "../.venv/Lib/site-packages/pyzbar/libiconv-2.dll;pyzbar/" `
  src\gui.py
Copy-Item config -Recurse dist/dist/config
Copy-Item template -Recurse dist/dist/template

因为它是一个GUI应用程序,所以我想添加--windowed选项,但是当我使用它运行它时,某处会出现错误" OSError:[WinError 6]句柄无效"。

PyInstaller如何工作

PyInstaller将Python和一组相关文件转换为可执行文件格式,并在运行时将其扩展到以下文件夹并执行。

%USERPROFILE%/ AppData /本地/温度/ _ [随机字母数字字符] /

此文件夹包含执行文件所需的pyd格式Python库,作为Python执行引擎的DLL,所需的库以及PyInstaller的--add-data--add-binary选项包含的文件。存储。

当应用程序完成运行时,该文件会自动删除(但是,它可能会保留在原处,例如当应用程序崩溃时,这种情况下它何时会消失是未知的)。

现在您可以看到PyInstaller创建的exe为何这么慢的原因(因为所有文件都在Temp文件夹中展开了。但是,我认为它对于容量来说太慢了,所以将来它可能会更快一点)与PyInstaller更新)。

是什么让您感到高兴?

例如,如果您在内部使用诸如Jinja2之类的模板引擎,并且希望将模板HTML文件嵌入exe中,或者要在应用程序的GUI上将存储在PyInstaller中的图标文件显示为图标,它是有效的。

可以使用sys.prefix获取此扩展文件夹的路径,因此,如果执行Path(sys.prefix) / "template" / "main.jinja"等操作,则可以读取作为模板嵌入的HTML文件 3

如前所述,您可以通过PyInstaller使用hasattr(sys, "frozen")Path(sys.argv[0]).prefix来确定该程序是否已被执行,因此可以使用它来切换图标文件或模板文件的引用路径,例如,可以创建可以正常运行的程序,无论是exe还是脚本。

但是,如前所述,关闭该应用程序后,将立即删除在执行exe时创建的文件夹。因此,即使将包含用户设置的文件放在此处并编辑结果,在关闭应用程序后也会将其立即删除,因此请务必小心。

  • lib找不到:api-ms-win-crt- *。DLL·问题#2068·pyinstaller / pyinstaller?

  • 常见问题解答·pyinstaller / pyinstaller Wiki?

  • 在python脚本中嵌入图标--Stack Overflow *底部答案中是否使用hasattr…sys.prefix

  • 运行已安装的软件包时出现ModuleNotFoundError·问题#98·pypa / pipenv?

  • Python 3.x-PyInstaller使用vlc和PyQt5对程序进行的exe转换不起作用。 (104186)| teratail(但我在这里没有使用该方法)?

  • [Python]如何将标准输出重定向到Tkinter文本小部件Python-2.7 | CODE Q