Load .whl packages and dependencies dynamically from python executable during runtime - python

I am quite new on python environment and on pyinstaller, but I really need your help.
Context
I have a python app which loads plugins within code. Indeed, we provide new features for our users in the form of plugins, and we want them to be able to install and use those that interest them. We don't want to build a new executable file every new plugin.
We bundled our app in a executable with pyinstaller, a one folder, because it seems easier to add plugins.
pyinstaller --clean --paths=lib/python3.8/site-packages src/main.py
My plugins have sometimes external dependencies (lib, etc.), so foreach plugin here is my setup.py (with requirements, values from requirements.txt file) :
setup(name='package_name',version='0.0.1',include_package_data=True,install_requires=requirements,extras_require={'all': requirements})
My issue
I know how to import installed modules dynamically to my code:
module=__import__(module_name,globals(),locals(),[name],0)
This part works.
But I have difficulties to install completely and dynamically those plugins within my code.
The solution must work on a linux ans Windows machine.
What I tried
Let's imagine I want to import my test.whl plugin, which has a dependency with 'test2' package
Install the plugin with pip:
subprocess.run(["pip", "install", "--upgrade", package, "-t", my_one_folder_location])
Pro: if python and pip are installed on the Host machine it works
Cons : You need to have python and "pip" (not "pip3" etc) on the user computer and the path. You have to be careful to have the same python version than on the package, etc. Not a recommanded solution...
I also tried to use the python installed in the pyinstaller folder but did not succeed.
Import every plugins in a specific directory:
PyInstaller understands the “egg” distribution format often used for Python packages. If your script imports a module from an “egg”, PyInstaller adds the egg and its dependencies to the set of needed files.
I tried to put my .wheel packages in a folder "egg". Then my program detect the plugin, but it doesn't import my lib dependencies
__main__:Unexpected error: no module named 'test2'
I'm going around in circles and can't find any solutions: What is the best way to import my external .whl packages and all it's dependencies in a pyinstaller solution?

Related

Install additional python package to an app compiled with PyInstaller

I have an app that is already compiled thanks to PyInstaller with a limited amount of python packages. The app has been compiled with the --onefile option. I'd like to add the possibility to install any new package in the temporary environment at the launch of the app, but there is no pip (it doesn't matter that the package needs to be installed at each run, this is a very specific option of my app).
While the app was running, I tried to copy/paste manually a random package in the temporary _MEIXXXXX folder. That's quite a dirty way but it worked, I could use the python package.
Do you know if it's possible to do so in a better way ?

Python exe imports

Need to Export a python project into an exe file.
I want to share it to people who don't have/use python.
The exe export still work on their respective computer?
Also, I have Pandas dependency import which requires a pip install. still work?
You should use PyInstaller, a package created to build standalone applications:
PyInstaller bundles a Python application and all its dependencies into a single package.
The user can run the packaged app without installing a Python
interpreter or any modules.
So in this case there won't be problems in using Pandas.

What is installing Python modules or packages?

A Python module is just a .py source file. A Python package is simply a collection of modules.
So why do we need programs such as pip to 'install' Python modules? Why not just download the files, put them in our project's folder and import them?
What exactly does it mean to 'install' a module or a package? And what exactly does pip do?
Are things different on Windows and on Linux?
So why do we need programs such as pip to 'install' Python modules? Why not just download the files, put them in our project's folder and import them?
It's just meant to facilitate the installation of softwares without having to bundle all the dependencies nor ask the user to download the files.
You can type pip install mysoftware and that will also install the required dependencies. You can also upgrade a software easily.
What exactly does it mean to 'install' a module or a package? And what exactly does pip do?
It will copy the files in a directory that is in your Python path. This way you will be able to import the package without having to copy the directory in your project.
With your proposal, for each and every project you have to download the required modules as dependencies. You have to download them again and again and add them with your project which is not very suitable though some platform like node.us do it.
What pip do is to keep the modules you installed in /use/lib/python*/site-packages/ so clearly it is included in your Python's path. So, when you try to import a module or package it checks in site-package if it exists. If exists,then this code will be used with your project. If not, you will get an error.

Specifying installation path of python modules from installed RPM

I have a simple python script that I have been trying to package into an RPM. This was a simple python script that you can run by calling "./". However, to package it into an RPM, I turned the script into a module with a init.py and setup.py. I was able to package it into an rpm using "python setup.py bdist_rpm" following https://docs.python.org/2.0/dist/creating-rpms.html . I was also able to install the created .noarch.rpm file into a different machine. However, I have no idea how to use this script now after I installed the .noarch.rpm file.
So, I successfully installed the .noarch.rpm file that has my script packaged into it, but I have no idea where this file is or how to use my script from this. This is my very first time creating an RPM, and I am fairly new to Python as well, so I think I am just missing something. Is there a way to specify where the python module is installed when I install the .noarch.rpm?
I am running on RHEL. I also looked at two other StackExchange questions/answers that are similar to what I want, but I still do not quite understand what to do. Here are the other questions/answers: Python distutils - Change Path RPM Installs To and Creating Python RPM
You can get list of files in your RPM package by:
rpm -qpl ./some_package.rpm
or when already installed:
rpm -ql some_package

Run a python script in an environment where a library may not be present

I have a python script where I am including a third party library:
from docx import Document.
Now, I need to run this script in an environment where bare-bones python is present but not this library.
Installing this library in the target environment is beyond my scope and I tried using distutils, but couldn't go far with it. The target environment just need to run the script, not install a package.
I am from Java background and in Java I would have just exported and created a jar file which would have included all the libraries I needed. I need to do similar with python.
Edit: With distutils, I tried creating a setup.py:
from distutils.core import setup
import docx
setup(name='mymodule',
version='1.0',
py_modules=['mymodule', docx]
)
But I am not sure this works.
PyInstaller won't work if you can't make a pyc file and you cannot make pyc file unless your code runs without fatal errors.
You could have the import in a try block that excepts ImportError 's but that will result in NameError 's where the package is referenced. Long story short if the package is integral to the script no amount of avoiding it will fix your problem. You need the dependencies.
You said installing the package is beyond your scope, well then, it is time to expand your scope. Docx is an open source package you can find on github here
You can download that and run setup.py
You can include the modules for docx in your application. Just distribute them together.
But docx depends on the lmxl operating system package and needs to run setup on that. You can't just copy it to the target machine.
I'm not sure PyInstaller supports docx, especially add it has the non python dependency.
Really using pip or easy_install is the way to go.
PyInstaller is a program that converts (packages) Python programs into stand-alone executables, under Windows, Linux, Mac OS X, Solaris and AIX.

Categories