python - 分发大型复杂 Python 项目以便其他用户完全安装它们而不考虑操作系统的最佳方式?

标签 python operating-system pip conda

如何确保分发具有较大依赖性的 Python 包(如 NumPy 和 SciPy)自动正确安装在用户的计算机上,而不管他们的操作系统如何?

问题是许多这样的包都或多或少地通过 pip 的主要 channel 安装,包括上面提到的那些......

最佳答案

我并不认为这是完美的,但下面是我在实践中发现的非常强大的东西:一个 install.sh 脚本,最初派生于一个名为 words2map 的人工智能库.目标是确保用户可以简单地运行 ./install.sh 然后所有需要的 pip install thispip install that 成功在任何情况下(即使是全新的服务器),无论您使用的是什么操作系统。 (我真的希望与操作系统无关的安装是行业标准,至少在 Mac OSX 和每个 Linux 发行版上都是这样……)

随意直接跳到代码,但对于那些需要解释的人:这个 install.sh 脚本在很大程度上依赖于 Conda 包分发管理器,它工作得非常好,因为它构建了操作系统-自动特定的轮子。下面的安装代码首先检查用户的操作系统,然后安装适当的 Conda 发行版(如果在 Mac OSX 和 Linux 上,在这种情况下),最后根据需要通过 Conda 安装所有剩余的依赖项。另外,请注意,如果检测到 Linux 终端,它首先确保所需的编译库可通过例如sudo apt-get install python-dev(因为用户经常缺少 gcc 或其他东西),最后这会自动将 Conda 添加到用户的 PATH 中以进行 bashzshell,这似乎涵盖了大多数终端(但也许不是,请随意添加)。很多花哨的东西,但实际上这提供了一个非常好的用户体验,可以帮助用户立即启动并运行您正在分发的新的复杂 Python 库,因为您可以通过尝试立即下载并运行 words2map 来自行测试。如果对每个人来说有意义/使它更好/更清晰,我们强烈建议对此进行编辑。好的,开始表演吧!

#!/bin/bash

download_miniconda() {
    echo "Downloading Miniconda for Python dependencies..."
    OS_BIT_TYPE="$(uname -m)"
    OS_ARCHITECTURE="$(uname -s)"
    if [ $OS_BIT_TYPE == "i686" ]; then
        OS_BIT_TYPE="x86"
    fi
    if [ $OS_ARCHITECTURE == "Darwin" ]; then
        OS_ARCHITECTURE="MacOSX"
    fi

    MINICONDA_INSTALL_FILE="Miniconda2-latest-$OS_ARCHITECTURE-$OS_BIT_TYPE.sh"
    MINICONDA_DOWNLOAD_URL="https://repo.continuum.io/miniconda/$MINICONDA_INSTALL_FILE"
    $(curl -O $MINICONDA_DOWNLOAD_URL)
    $(chmod +x $MINICONDA_INSTALL_FILE)
}

install_miniconda() {
    echo "Installing Miniconda..."
    echo "$(./$MINICONDA_INSTALL_FILE -b -p $HOME/miniconda)"
    echo "$(rm $MINICONDA_INSTALL_FILE)"    
}

confirm_miniconda_installed() {
    if hash conda 2>/dev/null; then
        echo "Miniconda installed!"
    else
        echo "Failed to install Miniconda. Please visit http://conda.pydata.org/docs/install/quick.html to install and then try rerunning this script, making sure that Miniconda is accessible in the PATH"
    fi
}

update_script_startup_file() {
    echo "if [[ \":\$PATH:\" != *\":\$HOME/miniconda/bin:\"* ]]; then" >> $STARTUP_FILE
    echo "  export PATH=\"\$PATH:\$HOME/miniconda/bin\"" >> $STARTUP_FILE
    echo "fi" >> $STARTUP_FILE
}

add_miniconda_to_path() {
    # temporary update to PATH for this script
    export PATH="$PATH:$HOME/miniconda/bin"

    # permanent update to PATH for user's convenience
    if [ -n "`$SHELL -c 'echo $BASH_VERSION'`" ]; then
        STARTUP_FILE="$HOME/.bashrc"
        update_script_startup_file
    elif [ -n "`$SHELL -c 'echo $ZSH_VERSION'`" ]; then
        STARTUP_FILE="$HOME/.zshrc"
        update_script_startup_file
    else
        echo "Couldn't automatically add Miniconda to the PATH of your preferred terminal. We suggest working from Bash or ZShell." 
    fi
}

install_conda_if_needed() {
    if hash conda 2>/dev/null; then
        echo "Miniconda installed!"
    else
        if ping -c 1 google.com >> /dev/null 2>&1; then
            download_miniconda
            install_miniconda
            add_miniconda_to_path
            confirm_miniconda_installed
        else
            echo "Looks like you're offline! Please address this and then try rerunning this script."
        fi
    fi
}

create_conda_environment() {
    if hash conda 2>/dev/null; then
        CONDA_ENVIRONMENTS="$(conda env list)"
        if [[ "$CONDA_ENVIRONMENTS" != *"words2map"* ]]; then
            conda create --name words2map --yes cython scikit-learn gensim seaborn
        fi
    fi
}

install_developer_libraries_as_needed() {
    OS_ARCHITECTURE="$(uname -s)"
    if [ $OS_ARCHITECTURE == "Linux" ]; then
        echo "$(python -mplatform | grep -qi Ubuntu && sudo apt-get update && sudo apt-get install python-dev || sudo yum update -y && sudo yum install python-devel -y && sudo yum groupinstall "Development Tools" -y)"
    fi
}

install_python_dependencies() {
    if hash conda 2>/dev/null; then
        echo 'Installing Python dependencies for words2map...'
        source activate words2map
        install_developer_libraries_as_needed
        pip install hdbscan pattern semidbm nltk unidecode
        source deactivate
    fi  
}

refresh_user_shell() {
    if [ -n "`$SHELL -c 'echo $BASH_VERSION'`" ]; then
        exec bash
    elif [ -n "`$SHELL -c 'echo $ZSH_VERSION'`" ]; then
        exec zsh
    fi
}

install_conda_if_needed
create_conda_environment
install_python_dependencies
refresh_user_shell

关于python - 分发大型复杂 Python 项目以便其他用户完全安装它们而不考虑操作系统的最佳方式?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38213861/

相关文章:

运行 pip install -e 后出现 python ModuleNotFoundError。

python - mac 操作系统 zsh : command not found: pip

python - 扩展pandas数据框并合并列

java - Java 中何时实际发生内存不足异常?

python - 有没有办法在 python 中调用左键单击?

linux - 什么是内存互锁?

operating-system - 无法理解Belady的异常

python - PIP 命令在虚拟环境中不起作用

python - 控制 matplotlib .svg 图形的类和 id 属性?

python:将年/月/日/时/分/秒转换为自 1970 年 1 月 1 日以来的 # 秒