分发大型复杂 Python 项目以便其他用户完全安装它们而不考虑操作系统的最佳方式?
Best way to distribute big, complex Python projects so that they fully install for other users, regardless of operating system?
如何确保分发具有较大依赖性的 Python 包,如 NumPy 和 SciPy,自动正确安装在用户的计算机上,而不管他们的 OS?
问题是许多这样的软件包都或多或少地通过 pip
的主要渠道安装,包括上面提到的那些...
我并不认为这是完美的,但以下是我在实践中发现的非常强大的内容:一个 install.sh
脚本,最初是为一个名为 [=20= 的人工智能库派生的].目标是确保用户可以简单地 运行 ./install.sh
然后所有需要的 pip install this
和 pip install that
在任何情况下都成功(即使是全新的服务器),无论您正在使用的操作系统。 (我真的希望 OS-agnostic 安装是行业标准,至少在 Mac OSX 和每个 Linux 发行版...)
随意直接跳到代码,但对于那些需要解释的人:这个 install.sh
脚本在很大程度上依赖于 Conda 包分发管理器,它确实有效很好,因为它会自动构建 OS-specific wheels。下面的安装代码首先检查用户的 OS,然后安装适当的 Conda 发行版(如果在 Mac OSX 和 Linux 上,在这种情况下),最后根据需要通过 Conda 安装所有剩余的依赖项。另外,请注意,如果检测到 Linux 终端,它首先确保所需的编译库可通过例如sudo apt-get install python-dev
(因为用户经常丢失 gcc
或其他东西),最后这会自动将 Conda 添加到用户的 PATH 中以获得 bash
和 zshell
,这似乎涵盖了大多数终端(但也许不是,请随意添加)。很多花里胡哨的东西,但实际上这提供了一个非常好的用户体验,可以帮助用户立即起床 运行 一个新的复杂的 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
legel 建议的问题是您最终仍然依赖用户的环境来部署您的应用程序。
过去我有过类似的安装脚本,它们会完成部署我的应用程序的所有脏活,但它仍然依赖网络连接来下载包和依赖项。我已经通过创建一个 docker 容器来解决这个问题。我会用我的应用程序和所有依赖项构建一个容器,创建一个新的 docker 图像并将 docker 图像提供给客户。唯一的依赖是在系统上有 docker,而 运行 我的应用程序的方法是使用 docker 运行.
还有另一种打包所有依赖项的方法是使用http://www.pyinstaller.org/,它创建一个独立的应用程序来打包所有依赖模块。不过免责声明:我还没有在任何大型应用程序上使用过它,刚刚开始测试它,到目前为止适用于较小的程序。
希望对您有所帮助!
如何确保分发具有较大依赖性的 Python 包,如 NumPy 和 SciPy,自动正确安装在用户的计算机上,而不管他们的 OS?
问题是许多这样的软件包都或多或少地通过 pip
的主要渠道安装,包括上面提到的那些...
我并不认为这是完美的,但以下是我在实践中发现的非常强大的内容:一个 install.sh
脚本,最初是为一个名为 [=20= 的人工智能库派生的].目标是确保用户可以简单地 运行 ./install.sh
然后所有需要的 pip install this
和 pip install that
在任何情况下都成功(即使是全新的服务器),无论您正在使用的操作系统。 (我真的希望 OS-agnostic 安装是行业标准,至少在 Mac OSX 和每个 Linux 发行版...)
随意直接跳到代码,但对于那些需要解释的人:这个 install.sh
脚本在很大程度上依赖于 Conda 包分发管理器,它确实有效很好,因为它会自动构建 OS-specific wheels。下面的安装代码首先检查用户的 OS,然后安装适当的 Conda 发行版(如果在 Mac OSX 和 Linux 上,在这种情况下),最后根据需要通过 Conda 安装所有剩余的依赖项。另外,请注意,如果检测到 Linux 终端,它首先确保所需的编译库可通过例如sudo apt-get install python-dev
(因为用户经常丢失 gcc
或其他东西),最后这会自动将 Conda 添加到用户的 PATH 中以获得 bash
和 zshell
,这似乎涵盖了大多数终端(但也许不是,请随意添加)。很多花里胡哨的东西,但实际上这提供了一个非常好的用户体验,可以帮助用户立即起床 运行 一个新的复杂的 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
legel 建议的问题是您最终仍然依赖用户的环境来部署您的应用程序。
过去我有过类似的安装脚本,它们会完成部署我的应用程序的所有脏活,但它仍然依赖网络连接来下载包和依赖项。我已经通过创建一个 docker 容器来解决这个问题。我会用我的应用程序和所有依赖项构建一个容器,创建一个新的 docker 图像并将 docker 图像提供给客户。唯一的依赖是在系统上有 docker,而 运行 我的应用程序的方法是使用 docker 运行.
还有另一种打包所有依赖项的方法是使用http://www.pyinstaller.org/,它创建一个独立的应用程序来打包所有依赖模块。不过免责声明:我还没有在任何大型应用程序上使用过它,刚刚开始测试它,到目前为止适用于较小的程序。
希望对您有所帮助!