Windows批处理文件运行Python脚本检查安装的包版本?

2024-04-19 02:23:21 发布

您现在位置:Python中文网/ 问答频道 /正文

我试图创建一个批处理文件来运行我编写的Python脚本,但遇到了一些障碍:

  1. 我需要确保最终用户安装了matplotlib-3.1.1或更高版本,因此我有一个命令:
C:\ProgramData\Anaconda3\python.exe -m pip freeze | findstr matplotlib

但这会产生一个输出:

^{pr2}$

所以问题是:我如何才能搜索到一个非常具体的包,而不是任何与搜索键大致匹配的包?在

  1. 如果用户的matplotlib版本比所需版本旧,我希望自动安装最新版本。如何将版本检查(上面)的输出发送到if子句中使用的某个变量?在

提前谢谢!在


Tags: pip文件用户命令版本脚本matplotlibexe
2条回答

how can I search for a very specific package rather than anything that roughly matches search key?

我怀疑您根本不需要这样做(跳到最后一节),尤其是不需要从批处理文件中执行此操作。在

如果您真的必须从批处理开始执行此操作,pip list输出可能比pip freeze更方便。它应提供表格输出,如下所示:

Package        Version Location
           -                       
package-name   1.0.0   c:\path\to\install\of\package-name

经过一番寻找和玩弄,我终于想出了:

^{pr2}$

(在脚本中,可能需要将百分号加倍)

然后您可以验证脚本中的%MPLVER%(不过,我不知道如何比较一个版本字符串来检查它是3.1.1还是更高版本)。在


在Python中实现这一点要容易得多:

import pkg_resources

def have_recent_mpl():
    try:
        pkg_resources.require('matplotlib>=3.1.1')
    except pkg_resources.VersionConflict:
        # out of date
        return False
    except pkg_resources.DistributionNotFound:
        # not installed
        return False
    return True

If user's version of matplotlib is older than what is required I want to have the latest version installed automatically.

你想解决问题的地方好像是错的。大概,您希望确保您有一个最新的matplotlib,因为您正在安装的其他东西需要它,是吗?所以您应该使用正确的packaging tools,并将所需的matplotlib版本指定为requirementin设置.py. 在

我完全同意在python中这样做比较容易,但是如果你真的想用批处理脚本(也许它是你最喜欢的语言,没有它你就做不到?)公司名称:

更新:现在可以正确处理版本字符串。在

@ECHO OFF
setlocal
setlocal EnableDelayedExpansion 

::  this is the package which you need version of
set packageName=matplotlib

::  this is the minimum version you want
set desiredVersion=3.1.1

::  this will be filled by called function
set versionString=""

call :GetPythonPackageVersionString %packageName% versionString
if %versionString% == "" (
    ECHO PACKAGE %packageName% IS NOT INSTALLED OR COULD NOT BE FOUND!
    exit /b 1
)


::  remove spaces at the start and end
call :TrimLeadingTrailingSpaces %versionString% versionString


set versionOk=""
call :CompareVersionStrings %versionString% %desiredVersion% versionOk
if %versionOk% == "" (
    ECHO PACKAGE VERSION TOO LOW
    ECHO PLEASE UPDATE %packageName% VERSION %desiredVersion%
    exit /b 3
) else (
    ECHO PACKAGE VERSION IS OK
    exit /b 0
)

::  end of main
goto:eof






::
::  helper function for getting version of a python package
::  arg 1:takes package name as string
::  arg 2 (return value): package version as string (eg "3.10.0" without quotes)
::
:GetPythonPackageVersionString
set "command1=pip show %~1"
set "command2=findstr /I version:"

::  check if package exists
set var=""
FOR /F "tokens=* USEBACKQ" %%F IN (`%command1%`) DO (
set var=%%F
)
if %var% == "" (
    set %2=""
    ECHO GetPythonPackageVersionString  - PACKAGE COULD NOT BE FOUND
    goto:eof
)

::  use pip show + findstr to capture version string
FOR /F "tokens=* USEBACKQ" %%F IN (`%command1% ^| %command2%`) DO (
set var=%%F
)
::  check result of findstr
if ERRORLEVEL 1 (
    set %2="" 
    ECHO GetPythonPackageVersionString  - FINDSTR UNABLE TO FIND
    goto:eof
)

::  get right side of the string
::separate by comma
set %2=
FOR /F "tokens=2 delims=:" %%f in ("%var%") DO (
    set %2=%%f
)
goto:eof



::
::  I found this function from
::  https://stackoverflow.com/questions/3001999/how-to-remove-trailing-and-leading-whitespace-for-user-provided-input-in-a-batch
::  answer of Foumpie
::
:TrimLeadingTrailingSpaces
set %2=%1
goto:eof




::
::  Compares to version strings
::  arg 1: version string captured from pip
::  arg 2: desired version string
::  arg 3(return value): empty or y
::
:CompareVersionStrings
::  separate by . character to get version numbers
for /f "tokens=1,2,3 delims=." %%a in ("%1") do (
   set packageVersionNumber[1]=%%a
   set packageVersionNumber[2]=%%b
   set packageVersionNumber[3]=%%c
)
::ECHO MAJOR VERSION:%packageVersionNumber[1]%
::ECHO MINOR VERSION:%packageVersionNumber[2]%
::ECHO SUBMINOR VERSION:%packageVersionNumber[3]%

for /f "tokens=1,2,3 delims=." %%a in ("%2") do (
   set desiredVersionNumber[1]=%%a
   set desiredVersionNumber[2]=%%b
   set desiredVersionNumber[3]=%%c
)
::ECHO MAJOR VERSION:%desiredVersionNumber[1]%
::ECHO MINOR VERSION:%desiredVersionNumber[2]%
::ECHO SUBMINOR VERSION:%desiredVersionNumber[3]%

for /L %%i IN (1 1 3) do (
    if !packageVersionNumber[%%i]! GTR !desiredVersionNumber[%%i]! (
        REM package version is larger than desired one
        set %3="y"
        goto:eof
    ) else if !packageVersionNumber[%%i]! EQU !desiredVersionNumber[%%i]! (
        REM this version number is equal, continue checking with next one
    ) else (
        REM package version is less than desired one
        set %3=""
        goto:eof
    )
)    

::  if we are here, all version numbers are equal
set %3="y"
goto:eof

相关问题 更多 >