Include python module (dependencies) installation in your python script

蓝咒 提交于 2021-01-14 23:38:52

问题


Is there a way to include/invoke python module(s) (dependencies) installation first, before running the actual/main script?

For example, in my main.py:

import os, sys
import MultipartPostHandler

def main():
    # do stuff here

But MultipartPostHandler is not yet installed, so what I want is to have it installed first before actually running main.py... but in an automated manner. When I say automatically, I mean I will just invoke the script one time to start the dependency installation, then to be followed by actual functionalities of the main script. (somehow, a little bit similar with maven. But I just need the installation part)

I already know the basics of setuptools. The problem is I may have to call the installation (setup.py) and the main script (main.py) separately.

Any ideas are greatly appreciated. Thanks in advance!


回答1:


Is there a way to include/invoke python module(s) (dependencies) installation first, before running the actual/main script?

  • A good way is to use setuptools and explicitly list them in install_requires.
  • Since you are providing a main function, you also probably want to provide entry_points.

I already know the basics of setuptools. The problem is I may have to call the installation (setup.py) and the main script (main.py) separately.

That is usually not a problem. It is very common to first install everything with a requirements.txt file and pip install -r requirements.txt. Plus if you list dependencies you can then have reasonable expectations that it will be there when your function is called and not rely on try/except ImporError. It is a reasonable approach to expect required dependencies to be present and only use try/except for optional dependencies.

setuptools 101:

create a tree structure like this:

$ tree
.
├── mymodule
│   ├── __init__.py
│   └── script.py
└── setup.py

your code will go under mymodule; let's imagine some code that does a simple task:

# module/script.py    

def main():
    try:
        import requests
        print 'requests is present. kudos!'
    except ImportError:
        raise RuntimeError('how the heck did you install this?')

and here is a relevant setup:

# setup.py

from setuptools import setup
setup(
    name='mymodule',
    packages=['mymodule'],
    entry_points={
        'console_scripts' : [
            'mycommand = mymodule.script:main',
        ]
    },
    install_requires=[
        'requests',
    ]
)

This would make your main available as a command, and this would also take care of installing the dependencies you need (e.g requests)

~tmp damien$ virtualenv test && source test/bin/activate && pip install mymodule/
New python executable in test/bin/python
Installing setuptools, pip...done.
Unpacking ./mymodule
  Running setup.py (path:/var/folders/cs/nw44s66532x_rdln_cjbkmpm000lk_/T/pip-9uKQFC-build/setup.py) egg_info for package from file:///tmp/mymodule

Downloading/unpacking requests (from mymodule==0.0.0)
  Using download cache from /Users/damien/.pip_download_cache/https%3A%2F%2Fpypi.python.org%2Fpackages%2F2.7%2Fr%2Frequests%2Frequests-2.4.1-py2.py3-none-any.whl
Installing collected packages: requests, mymodule
  Running setup.py install for mymodule

    Installing mycommand script to /tmp/test/bin
Successfully installed requests mymodule
Cleaning up...
(test)~tmp damien$ mycommand 
requests is present. kudos!

more useful commands with argparse:

If you want to use argparse then...

# module/script.py

import argparse

def foobar(args):
    # ...

def main():
    parser = argparse.ArgumentParser()
    # parser.add_argument(...)
    args = parser.parse_args()
    foobar(args)



回答2:


You should use the imp module. Here's a example:

import imp
import httplib2
import sys

try:
  import MultipartPostHandler
except ImportError:
  # Here you download 
  http = httplib2.Http()
  response, content = http.request('http://where_your_file_is.com/here')
  if response.status == 200:
    # Don't forget the right managment
    with open('MultipartPostHandler.py', 'w') as f:
     f.write(content)
    file, pathname, description = imp.find_module('MultipartPostHandler')
    MultipartPostHandler = imp.load_module('MultipartPostHandler', file, pathname, description)
  else:
    sys.exit('Unable to download the file')

For a full approach, use a queue:

download_list = []
try:
    import FirstModule
except ImportError:
    download_list.append('FirstModule')

try:
    import SecondModule
except ImportError:
    download_list.append('SecondModule')

if download_list:
    # Here do the routine to dowload, install and load_modules

# THe main routine
def main():
    the_response_is(42)

You can download binaries with open(file_content, 'wb')

I hope it help

BR




回答3:


There's a few ways to do this. One way is to surround the import statement with a try...except ImportError block and then have some Python code that installs the package if the ImportError exception is raised, so something like:

try:
    import MultipartPostHandler
except ImportError:
    # code that installs MultipartPostHandler and then imports it

I don't think this approach is very clean. Plus if there are other unrelated importing issues, that won't be detected here. A better approach might be to have a bash script that checks to see if the module is installed:

pip freeze | grep MultipartPostHandler

and if not, installs the module:

pip install MultipartPostHandler

Then we can safely run the original Python code.

EDIT: Actually, I like FLORET's answer better. The imp module is exactly what you want.



来源:https://stackoverflow.com/questions/26081948/include-python-module-dependencies-installation-in-your-python-script

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!