python - Python subproccess.run 不适用于 Pyinstaller
问题描述
考虑以下名为 test.py 的 python (3.9) 脚本:
import sys
import os
import subprocess
from pathlib import Path
# This is for pyinstaller (as main_dir = sys.path[0] won't work)
if getattr(sys, 'frozen', False):
main_dir = os.path.dirname(sys.executable)
else:
main_dir = os.path.dirname(os.path.abspath(__file__))
processes_dir = Path(main_dir, "processes")
outfile = Path(main_dir, "output.txt")
# Initialize the output text file
with open(outfile, 'w') as f:
f.write('')
# This calls A1.py (see below)
result = subprocess.run([sys.executable, Path(processes_dir, "A1.py")], input="1\n2", capture_output=True, text=True)
# If an error is raised, it's written to output.txt; stdout is written to output.txt
if result.stderr:
with open(outfile, 'a') as f:
f.write("{0}\n\n".format(result.stderr))
else:
with open(outfile, 'a') as f:
f.write("{0}\n\n".format(result.stdout))
subprocess.run 调用以下简单脚本:
x1 = int(input())
x2 = int(input())
print(x1+x2)
这运行得很好。我正在尝试研究如何使用 Pyinstaller 将其转换为可执行文件 (.exe)。在适当的目录中,我运行:
pyinstaller --onefile test.py
这将成功构建 test.exe。当我运行 test.exe(从 cmd 或双击文件)时,它打开时没有错误,产生一个空的 output.txt,然后只是无限期地挂起。看来 subprocess.run 无法与 pyinstaller 一起正常工作。让 test.exe 与 pyinstaller 一起工作的任何想法/建议?
解决方案
这里发生的情况是,当脚本未编译时,sys.executable
返回python可执行文件 ( C:\Users\randomuser\AppData\Local\Programs\Python38
),但在编译代码时,sys.executable 返回您创建的 .exe 文件。因此,您的 .exe 文件会调用自己,无限次地再次调用自己,哈哈。
您可以通过两种不同(简单)的方式解决此问题:
(如果您想分发 exe 文件,则不太推荐,因为它取决于 python 安装):
替换sys.executable
为'python'
. 这将确保脚本使用 Python 执行,而不是使用您自己的 .exe 文件(如果已编译):result = subprocess.run(['python', Path(processes_dir, "A1.py")], input="1\n2", capture_output=True, text=True)
您可以导入
A1.py
脚本(确保脚本与可执行文件位于同一文件夹中,并使主代码位于名为 main 的函数中,将结果作为字符串返回):
然后,您将能够运行import A1
,并调用主程序 running A1.main()
:
import sys
import os
import subprocess
import A1
from pathlib import Path
# This is for pyinstaller (as main_dir = sys.path[0] won't work)
if getattr(sys, 'frozen', False):
main_dir = os.path.dirname(sys.executable)
else:
main_dir = os.path.dirname(os.path.abspath(__file__))
processes_dir = Path(main_dir, "processes")
outfile = Path(main_dir, "output.txt")
# Initialize the output text file
with open(outfile, 'w') as f:
f.write('')
# This calls A1.py (see below)
result = A1.main()
# The output is written into output.txt.
with open(outfile, 'a') as f:
f.write("{0}\n\n".format(result))
您可以考虑使用 try-except 子句和 traceback 模块捕获错误回溯
pyinstaller 命令应该是:pyinstaller --onefile test.py --add-data "A1.py;."
推荐阅读
- javascript - 使用 GET 请求动态填充表
- python - Numpy Matmul 导致错误说模块没有属性 matmul
- java - 将 Actions 变量发送到方法
- php - 我想将网页的某些部分调用/拉到另一个页面中
- javascript - mongoose put 方法作为 post 方法工作
- mysql - 如何计算体育投注的责任
- javascript - Laravel Mix 说“构建成功”,但在 resources/app.js 中所做的更改不会执行
- algorithm - 使用数学优先级将后缀转换为后缀
- python - 无法使 find.all(string='television') 与 BeautifulSoup (Python 3.x) 一起使用
- javascript - 如何隐藏画布或任何其他对象?