How to install and import Python modules at runtime - python
I want to write a script to automatically setup a brand new ubuntu installation and install a django-based app. Since the script will be run on a new server, the Python script needs to automatically install some required modules.
Here is the script.
#!/usr/bin/env python
import subprocess
import os
import sys
def pip_install(mod):
print subprocess.check_output("pip install %s" % mod, shell=True)
if __name__ == "__main__":
if os.getuid() != 0:
print "Sorry, you need to run the script as root."
sys.exit()
try:
import pexpect
except:
pip_install('pexpect')
import pexpect
# More code here...
The installation of pexpect is success, however the next line import pexpect is failed. I think its because at runtime the code doesn't aware about the newly installed pexpect.
How to install and import Python modules at runtime? I'm open to another approaches.
You can import pip instead of using subprocess:
import pip
def install(package):
pip.main(['install', package])
# Example
if __name__ == '__main__':
try:
import pexpect
except ImportError:
install('pexpect')
import pexpect
Another take:
import pip
def import_with_auto_install(package):
try:
return __import__(package)
except ImportError:
pip.main(['install', package])
return __import__(package)
# Example
if __name__ == '__main__':
pexpect = import_with_auto_install('pexpect')
print(pexpect)
[edit]
You should consider using a requirements.txt along with pip. Seems like you are trying to automate deployments (and this is good!), in my tool belt I have also virtualenvwrapper, vagrant and ansible.
This is the output for me:
(test)root#vagrant:~/test# pip uninstall pexpect
Uninstalling pexpect:
/usr/lib/python-environments/test/lib/python2.6/site-packages/ANSI.py
/usr/lib/python-environments/test/lib/python2.6/site-packages/ANSI.pyc
/usr/lib/python-environments/test/lib/python2.6/site-packages/FSM.py
/usr/lib/python-environments/test/lib/python2.6/site-packages/FSM.pyc
/usr/lib/python-environments/test/lib/python2.6/site-packages/fdpexpect.py
/usr/lib/python-environments/test/lib/python2.6/site-packages/fdpexpect.pyc
/usr/lib/python-environments/test/lib/python2.6/site-packages/pexpect-2.4-py2.6.egg-info
/usr/lib/python-environments/test/lib/python2.6/site-packages/pexpect.py
/usr/lib/python-environments/test/lib/python2.6/site-packages/pexpect.pyc
/usr/lib/python-environments/test/lib/python2.6/site-packages/pxssh.py
/usr/lib/python-environments/test/lib/python2.6/site-packages/pxssh.pyc
/usr/lib/python-environments/test/lib/python2.6/site-packages/screen.py
/usr/lib/python-environments/test/lib/python2.6/site-packages/screen.pyc
Proceed (y/n)? y
Successfully uninstalled pexpect
(test)root#vagrant:~/test# python test.py
Downloading/unpacking pexpect
Downloading pexpect-2.4.tar.gz (113Kb): 113Kb downloaded
Running setup.py egg_info for package pexpect
Installing collected packages: pexpect
Running setup.py install for pexpect
Successfully installed pexpect
Cleaning up...
<module 'pexpect' from '/usr/lib/python-environments/test/lib/python2.6/site-packages/pexpect.pyc'>
(test)root#vagrant:~/test#
For those who are using pip version greater than 10.x, there is no main function for pip so the alternative approach is using import pip._internal as pip instead of import pip like :
Updated answer of Paulo
import pip._internal as pip
def install(package):
pip.main(['install', package])
if __name__ == '__main__':
try:
import pexpect
except ImportError:
install('pexpect')
import pexpect
I actually made a module for this exact purpose (impstall)
It's really easy to use:
import impstall
impstall.now('pexpect')
impstall.now('wx', pipName='wxPython')
Github link for issues/contributions
I solved my problem using the imp module.
#!/usr/bin/env python
import pip
import imp
def install_and_load(package):
pip.main(['install', package])
path = '/usr/local/lib/python2.7/dist-packages'
if path not in sys.path:
sys.path.append(path)
f, fname, desc = imp.find_module(package)
return imp.load(package, f, fname, desc)
if __name__ == "__main__":
try:
import pexpect
except:
pexpect = install_and_load('pexpect')
# More code...
Actually the code is less than ideal, since I need to hardcode the Python module directory. But since the script is intended for a known target system, I think that is ok.
I had the same issue but none of Google's searches helped. After hours debugging, I found that it may be because the sys.path is not reloaded with new installation directory.
In my case on my Ubuntu Docker, I want to import dns.resolver at runtime for Python3.8 (pre-installed). I also created ubuntu user and run all things with this user (including my Python script).
Before installing, sys.path doesn't have /home/ubuntu/.local/lib/python3.8/site-packages since I didn't install anything.
While installing with subprocess or pip.main like above, it creates /home/ubuntu/.local/lib/python3.8/site-packages (as user installation).
After installing , the sys.path should be refreshed to include this new location.
Since the sys.path is managed by site module, we should reload it (ref HERE):
import site
from importlib import reload
reload(site)
The full block for anyone that needs:
import subprocess
import sys
try:
import dns.resolver
except ImportError:
subprocess.check_call([sys.executable, "-m", "pip", "install", "dnspython"])
import site
from importlib import reload
reload(site)
import dns.resolver
I'm not Python developer so these code can be simplify more. This may help in cases such as fresh CI/CD environment for DevOps engineers like me.
Related
client side how to use python script, installing package
I added some code snippets to python script and sent him to client. There is new library, does the the other side to install also package? pip install pywin32 code that added by me to script is; import win32com.client xl = win32com.client.Dispatch("Excel.Application") #instantiate excel app wb = xl.Workbooks.Open(r'C:\Users\jay\Desktop\PythonInOffice\python_run_macro\macro.xlsm') xl.Application.Run('macro.xlsm!Module1.macro1("Jay")') wb.Save() xl.Application.Quit() From answers': if I write the code below do I need to install sys and subprocess separetely also? import subprocess import sys def install('pywin32'): subprocess.check_call([sys.executable, "-m", "pip", "install", 'pywin32'])
Hope below code helps Normally check for if package there if not installs it import sys import subprocess import pkg_resources required = {'pywin32'} installed = {pkg.key for pkg in pkg_resources.working_set} missing = required - installed if missing: python = sys.executable subprocess.check_call([python, '-m', 'pip', 'install', *missing], stdout=subprocess.DEVNULL) NOTE:- if proxy being used, it won't work. on check_call enter proxy details to install
How to import the google api client into python so that it runs with as a cronjob?
I am trying to use the google API client to download something every day for something but I have deduced that for some reason it won't let me import googleapiclient when I run it in crontab. For example, if I run this in crontab crontab: * * * * * python3 test.py >> cron.log test.py: print("Hello") cron.log outputs: Hello But if I then once I import it so the file look like this from googleapiclient import discovery print("Hello") then the cron.log looks like this: Its just empty. I can not figure out why this is true. The google API client I believe is installed correctly because when I run it manually then it works perfectly with no issues. The operating system I am using is macos.
The way I fixed it is first by changing the crontab to python3 test.py > cron.log 2>&1. This showed that the errors where. Then I realized that it was not able to import googleapiclient into python. I still did not understand why it does not, but a workaround I found was to first install the libraries into a folder and then accessing the libraries from there. To install the libraries into a folder the command I used in terminal is below: pip3 install --upgrade google-api-python-client google-auth-httplib2 google-auth-oauthlib -t ./lib Then inside the python I added whats below to the beginning of the file so it would know where to import the libraries from. import os import sys file_path = os.path.dirname(__file__) module_path = os.path.join(file_path, "lib") sys.path.append(module_path) This does work.
import or install module from a command line script
I have a script that looks like this: import pip import sys def main(argv): ...[does stuff]... if __name__ == "__main__": main(sys.argv[1:]) I would like to implement this function i found on stack that imports a package (or install it if nescessary). def import_or_install(package): try: __import__(package) except ImportError: pip.main(['install', package]) My vision is that if i run a script on a random computer, if the packaged needed to run said script are not installed, the script does it automatically; Otherwise, import the module. When I try to run it, I get a NameError stating that the modules I call within main() are not defined. Link to where I found the function: Check if module exists, if not install it
What I understand in Question, if something like this : import pip not_installed = [] try: import test1 except ImportError,err: k= str(err).split(' ') not_installed.append(k[-1]) for i in not_installed: pip.main(['install',i]) Here test1 is the file to be run, convert it to cli accordingly P.S: Checked for 1 import error message
How to use virtualenv and pip in python
I'd like to have a python script which in the beginning create a virtual environment, install required modules (e.g. cherrypy) and then continues with the rest of the code. What I found so far is as follow: import os, virtualenv HOME_DIRECTORY = "venv" virtualenv.create_environment(HOME_DIRECTORY) execfile(os.path.join(HOME_DIRECTORY, "bin", "activate_this.py")) import pip pip.main(["install", "--prefix", HOME_DIRECTORY, "cherrypy"]) import cherrypy class Root(object): #cherrypy.expose def index(self): return "Hello World!" if __name__ == '__main__': cherrypy.quickstart(Root(), '/') The script creates virtual environment and install cherrypy (based on the log), but still I get ImportError: No module named cherrypy error. I also tried the following, but got the same error: import importlib CHERRYPY = 'cherrypy' try: importlib.import_module(CHERRYPY) except ImportError: import pip pip.main(["install", "--prefix", HOME_DIRECTORY, CHERRYPY]) finally: globals()[CHERRYPY] = importlib.import_module(CHERRYPY) Apart from the above problem, also, I'd like to know how to specify the python version (e.g. python 3.6) while creating virtual environment. Thanks.
For the record the issue was with the virtual environment activate (the line to execute activate_this.py). For Python 3 the following worked for me: ACTIVATE_THIS = 'venv/bin/activate_this.py' exec(Path(ACTIVATE_THIS).read_text(), dict(__file__ = ACTIVATE_THIS))
Check if module exists, if not install it
I want to check if a module exists, if it doesn't I want to install it. How should I do this? So far I have this code which correctly prints f if the module doesn't exist. try: import keyring except ImportError: print 'f'
import pip def import_or_install(package): try: __import__(package) except ImportError: pip.main(['install', package]) This code simply attempt to import a package, where package is of type str, and if it is unable to, calls pip and attempt to install it from there.
Here is how it should be done, and if I am wrong, please correct me. However, Noufal seems to confirm it in another answer to this question, so I guess it's right. When writing the setup.py script for some scripts I wrote, I was dependent on the package manager of my distribution to install the required library for me. So, in my setup.py file, I did this: package = 'package_name' try: return __import__(package) except ImportError: return None So if package_name was installed, fine, continue. Else, install it via the package manager which I called using subprocess.
This approach of dynamic import work really well in cases you just want to print a message if module is not installed. Automatically installing a module SHOULDN'T be done like issuing pip via subprocess. That's why we have setuptools (or distribute). We have some great tutorials on packaging, and the task of dependencies detection/installation is as simple as providing install_requires=[ 'FancyDependency', 'otherFancy>=1.0' ]. That's just it! But, if you really NEED to do by hand, you can use setuptools to help you. from pkg_resources import WorkingSet , DistributionNotFound working_set = WorkingSet() # Printing all installed modules print tuple(working_set) # Detecting if module is installed try: dep = working_set.require('paramiko>=1.0') except DistributionNotFound: pass # Installing it (anyone knows a better way?) from setuptools.command.easy_install import main as install install(['django>=1.2'])
NOTE: Ipython / Jupyter specific solution. While using notebooks / online kernels, I usually do it using systems call. try: import keyring except: !pip install keyring import keyring P.S. One may wish to call conda install or mamba install instead.
You can use os.system as follows: import os package = "package_name" try: __import__package except: os.system("pip install "+ package)
You can launch pip install %s"%keyring in the except part to do this but I don't recommend it. The correct way is to package your application using distutils so that when it's installed, dependencies will be pulled in.
Not all modules can be installed so easily. Not all of them have easy-install support, some can only be installed by building them.. others require some non-python prerequisites, like gcc, which makes things even more complicated (and forget about it working well on Windows). So I would say you could probably make it work for some predetermined modules, but there's no chance it'll be something generic that works for any module.
I made an import_neccessary_modules() function to fix this common issue. # ====================================================================================== # == Fix any missing Module, that need to be installed with PIP.exe. [Windows System] == # ====================================================================================== import importlib, os def import_neccessary_modules(modname:str)->None: ''' Import a Module, and if that fails, try to use the Command Window PIP.exe to install it, if that fails, because PIP in not in the Path, try find the location of PIP.exe and again attempt to install from the Command Window. ''' try: # If Module it is already installed, try to Import it importlib.import_module(modname) print(f"Importing {modname}") except ImportError: # Error if Module is not installed Yet, the '\033[93m' is just code to print in certain colors print(f"\033[93mSince you don't have the Python Module [{modname}] installed!") print("I will need to install it using Python's PIP.exe command.\033[0m") if os.system('PIP --version') == 0: # No error from running PIP in the Command Window, therefor PIP.exe is in the %PATH% os.system(f'PIP install {modname}') else: # Error, PIP.exe is NOT in the Path!! So I'll try to find it. pip_location_attempt_1 = sys.executable.replace("python.exe", "") + "pip.exe" pip_location_attempt_2 = sys.executable.replace("python.exe", "") + "scripts\pip.exe" if os.path.exists(pip_location_attempt_1): # The Attempt #1 File exists!!! os.system(pip_location_attempt_1 + " install " + modname) elif os.path.exists(pip_location_attempt_2): # The Attempt #2 File exists!!! os.system(pip_location_attempt_2 + " install " + modname) else: # Neither Attempts found the PIP.exe file, So i Fail... print(f"\033[91mAbort!!! I can't find PIP.exe program!") print(f"You'll need to manually install the Module: {modname} in order for this program to work.") print(f"Find the PIP.exe file on your computer and in the CMD Command window...") print(f" in that directory, type PIP.exe install {modname}\033[0m") exit() import_neccessary_modules('art') import_neccessary_modules('pyperclip') import_neccessary_modules('winsound')
Here is my approach. The idea is loop until python has already installed all modules by built in module as "pip" . import pip while True: try: #import your modules here. ! import seaborn import bokeh break except ImportError as err_mdl: print((err_mdl.name)) pip.main(['install', err_mdl.name])
I tried installing transformers using the below method and it worked fine. Similarly, you can just replace your library name instead of "transformers". import pip try: from transformers import pipeline except ModuleNotFoundError: pip.main(['install', "transformers"]) from transformers import pipeline
I tried this in a new virtual envoirnment with no packages installed and it installed the necessary package i.e. opencv-python Example is given below import os try: import cv2 except ImportError: os.system('pip install opencv-python')