I have built a bundled Python application that is a composition of an installed (ie " *.exe
", via pyinstaller
) and a code (ie " *.py
") part. This is due to a package that does not support installation, thus I have to call it directly from source.
I am able to distribute and run the application by including in the bundle my environment in .\venv
and running the code via .\venv\Scripts\python.exe my_script.py
, however it requires Python installed onto the machine, raising an Error otherwise
No Python at 'C:\Python38\python.exe'
Is there a way to include Python38
folder in my package to allow anyone to start the application regardless of Python installed or not (and its version)? I've tried to:
Python38
folder within package and within .\venv\Scripts\
hoping that .\venv\Scripts\python.exe
was searching there before looking in C:\
-> not workingPython38
in my package and force its copy in C:\
as the very first instruction -> it works, but it seems like cheating, and it may mess up things on recipient's computerI managed to solve the problem in a somehow easy way:
Python38
in my package together with my venv
(obviously, they cause the destination folder to grow in size, but it is not a big issue for my purposes).\venv\pyvenv.cfg
changing from absolute path to Python on my computer to a relative path inside the destination folderHere a reference to the updated pyvenv.cfg
:
home = .\Python38 <-- updated: it was "C:\Python38"
implementation = CPython
version_info = 3.8.5.final.0
virtualenv = 20.4.7
include-system-site-packages = false
base-prefix = .\Python38 <-- updated
base-exec-prefix = .\Python38 <-- updated
base-executable = .\Python38\python.exe <-- updated
FYI, here the code I used to automatically update the pyvenv.cfg
, that works with different python versions and paths:
import os
import re
from configparser import ConfigParser
# Set original and updated config paths
venv_cfg = 'pyvenv.cfg'
in_venv_cfg = os.path.join('.', 'venv', venv_cfg)
out_venv_cfg = os.path.join('.', 'config', venv_cfg) # changing folder to avoid override of venv config
# Parse data in config
with open(in_venv_cfg, 'r') as f:
config_lines = f.readlines()
config = ConfigParser()
config.read_string('[cfg]\n' + ''.join(config_lines))
# Get python version and location
py_path = config.get('cfg', 'home')
py_dir, py_name = os.path.dirname(py_path), os.path.basename(py_path)
# Update paths to python and save venv configuration
new_config_lines = [re.sub(r'(=\s*)' + py_dir.replace("\\", r"\\") + f'({py_name})', r'\1.\\\2', line) for line in config_lines]
with open(out_venv_cfg, 'w') as f:
f.writelines(new_config_lines)
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.