I've developed a QGIS plugin that needs to have installed external libraries to work. While I was working I've installed those libraries with pip command via osgeo4W shell but I don't want to each one on my company that want tot use the plugin have to go to the osgeo4W shell to install it. I'm not able to make my code running correctly to automatically install libraries when install the plugin. I've tried with multiple ways, last one is that but seems to do nothing... and by now I'm a little bit lost on my purpose.
main plugin file:
if os.path.isfile('install_deps.py'):
print('WARNING: new dependies will be installed....')
import install_deps
install_deps.installer_func
os.rename('install_deps.py', 'install_deps.installed')
else:
pass
install_deps.py file
import os
def installer_func():
plugin_dir = pathlib.Path(__file__).parent.parent
try:
import pip
except ImportError:
exec(
open(str(pathlib.Path(plugin_dir, 'scripts', 'get_pip.py'))).read()
)
import pip
# just in case the included version is old
pip.main(['install', '--upgrade', 'pip'])
sys.path.append(plugin_dir)
with open(str(plugin_dir / 'requirements.txt'), "r") as requirements:
for dep in requirements.readlines():
dep = dep.strip().split("==")[0]
try:
__import__(dep)
except ImportError as e:
print("{} not available, installing".format(dep))
pip.main(['install', dep])
requirements.txt file:
fuzzywuzzy==0.19.0
Unidecode==1.3.2
Can you help me?
3 Answers 3
I had exactly the same problem. When you use pip.main, you should get a warning saying that you are using an old script that will be removed in future versions of pip, so I would not recommend using this. What I did was to deal with requirements.txt through a bat file. I give you an example of a small script to generate and run the bat on the fly. You can adapt this to your case and run it at the start or installation of the plugin.
Code
import os
import sys
import subprocess
from pathlib import Path
#definition of the bat file as as string
#it will be equivalent to manually type these commands line by line
batF="""@echo off
call "->QGISPATH<-\\o4w_env.bat"
call "py3_env"
call python -m pip install -r \"->HOMEPATH<-requirements.txt\"
call exit
@echo on
"""
# then the idea is to find the osgeo4w shell path
# sys.executable is the base execution path and contains o4w_env.bat
# o4w_env.bat setup the osgeo4w shell
qgispath = str(os.path.dirname(sys.executable))
# here you replace the string ->QGISPATH<- with qgis path
# so that the script is installation independant
batF = batF.replace("->QGISPATH<-",qgispath)
# and the string ->HOMEPATH<- with the path to your requirements.txt
batF = batF.replace("->HOMEPATH<-",yourRequirementsPath)
# then you write it to a .bat file and run it
with open("pathToTheBat.bat","w") as f:
f.write(batF)
subprocess.run(["pathToTheBat.bat"])
Comments
It is equivalent to open osgeo4w and install requirements.
It may not be what your are looking for. Specifically, you cannot properly handle the errors that could occur during the package installation as you are running python through a batch file.
-
Thank you for the answer! How do you make sure the script is run only at installation and not each time the plugin is loaded?Boris CALVET– Boris CALVET2025年02月11日 10:59:50 +00:00Commented Feb 11 at 10:59
The suggested solutions here are Windows specific, as they use .bat files. What we've done is put some instructions in the metadata.txt for the plugin, in the about section, so the user sees it in the plugin information. We instruct the user to type commands in the Python Console:
Before using this plugin, open the QGIS menu and pick: 'Plugins | Python Console' Then enter the following:
import pip
pip.main(["install","package_name_1","package_name_2"])
Now, check that the packages were installed with:
import package_name_1
import package_name_2
If the install process reports a non-standard install location, you may need to add it to the path by typing:
import sys
sys.path.append('<install location>')
This seems to work for both Windows and Mac installations, even for underprivileged users.
In some old computers pip is not installed. I heard that some people included get_pip.py in their plugin, and then execute that if necessary, to make sure pip is installed before it gets used. But, we haven't needed to do this yet.
In the end I came up with a similar solution:
I've created a .bat file
@echo off
set "input=C:\Program Files\QGIS 3.16"
echo %input%
@echo ON
cd /d %~dp0
call py3-env.bat "%input%"
python3 -m pip install --upgrade pip
python3 -m pip install fuzzywuzzy
python3 -m pip install Unidecode
and I run it from main plugin file as
import subprocess
install_modules = location of my "pip_install_packages.bat" file
subprocess.run([install_modules], shell=True)
It works for me.
Explore related questions
See similar questions with these tags.