[python] 파이썬 패키지가 프로그래밍 방식으로 최신 버전인지 확인하는 방법은 무엇입니까?

패키지에서 프로그래밍 방식으로 스크립트의 최신 버전인지 확인하고 true 또는 false를 반환하는 방법은 무엇입니까?

다음과 같은 스크립트로 확인할 수 있습니다.

package='gekko'
import pip
if hasattr(pip, 'main'):
    from pip import main as pipmain
else:
    from pip._internal import main as pipmain
pipmain(['search','gekko'])

또는 명령 줄을 사용하여 :

(base) C:\User>pip search gekko
gekko (0.2.3)  - Machine learning and optimization for dynamic systems
  INSTALLED: 0.2.3 (latest)

그러나 프로그래밍 방식으로 확인하고 true 또는 false를 어떻게 반환합니까?



답변

빠른 버전 (패키지 확인 만)

아래 코드는와 같은 사용할 수없는 버전으로 패키지를 호출합니다 pip install package_name==random. 호출은 사용 가능한 모든 버전을 반환합니다. 이 프로그램은 최신 버전을 읽습니다.

그런 다음 프로그램이 실행 pip show package_name되고 패키지의 현재 버전을 가져옵니다.

일치하는 것을 찾으면 True를, 그렇지 않으면 False를 반환합니다.

이것은 신뢰할 수있는 옵션입니다. pip

import subprocess
import sys
def check(name):
    latest_version = str(subprocess.run([sys.executable, '-m', 'pip', 'install', '{}==random'.format(name)], capture_output=True, text=True))
    latest_version = latest_version[latest_version.find('(from versions:')+15:]
    latest_version = latest_version[:latest_version.find(')')]
    latest_version = latest_version.replace(' ','').split(',')[-1]

    current_version = str(subprocess.run([sys.executable, '-m', 'pip', 'show', '{}'.format(name)], capture_output=True, text=True))
    current_version = current_version[current_version.find('Version:')+8:]
    current_version = current_version[:current_version.find('\\n')].replace(' ','')

    if latest_version == current_version:
        return True
    else:
        return False

다음 코드는 다음을 호출합니다 pip list --outdated.

import subprocess
import sys

def check(name):
    reqs = subprocess.check_output([sys.executable, '-m', 'pip', 'list','--outdated'])
    outdated_packages = [r.decode().split('==')[0] for r in reqs.split()]
    return name in outdated_packages


답변

내 프로젝트 johnnydep에는이 기능이 있습니다.

쉘에서 :

pip install --upgrade pip johnnydep
pip install gekko==0.2.0

파이썬에서 :

>>> from johnnydep.lib import JohnnyDist
>>> dist = JohnnyDist("gekko")
>>> dist.version_installed
'0.2.0'
>>> dist.version_latest
'0.2.3'


답변

편집 : 핍 검색 제거

몇 가지 제안에 감사드립니다. 사용하지 않는 새 버전은 다음과 같습니다.pip search Daniel Hill이pypi 제안한 최신 버전을 직접 가져 오는 . 또한 하위 문자열이 일치하지 않는 문제를 해결합니다.

def check(name):
    import subprocess
    import sys
    import json
    import urllib.request

    # create dictionary of package versions
    pkgs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
    keys = [p.decode().split('==')[0] for p in pkgs.split()]
    values = [p.decode().split('==')[1] for p in pkgs.split()]
    d = dict(zip(keys, values)) # dictionary of all package versions

    # retrieve info on latest version
    contents = urllib.request.urlopen('https://pypi.org/pypi/'+name+'/json').read()
    data = json.loads(contents)
    latest_version = data['info']['version']

    if d[name]==latest_version:
        print('Latest version (' + d[name] + ') of '+str(name)+' is installed')
        return True
    else:
        print('Version ' + d[name] + ' of '+str(name)+' not the latest '+latest_version)
        return False

print(check('gekko'))

독창적 인 답변

다음은 gekko관심 패키지 에서만 최신 버전 정보를 검색하는 빠른 솔루션입니다 .

def check(name):
    import subprocess
    import sys
    # create dictionary of package versions
    pkgs = subprocess.check_output([sys.executable, '-m', 'pip', 'freeze'])
    keys = [p.decode().split('==')[0] for p in pkgs.split()]
    values = [p.decode().split('==')[1] for p in pkgs.split()]
    d = dict(zip(keys, values)) # dictionary of all package versions

    # retrieve info on latest version
    s = subprocess.check_output([sys.executable, '-m', 'pip', 'search', name])

    if d[name] in s.decode():  # weakness
        print('Latest version (' + d[name] + ') of '+str(name)+' is installed')
        return True
    else:
        print(s.decode())
        return False

print(check('gekko'))

그러면 메시지가 생성되고 최신 버전 (또는 최신 버전 이 아닌 경우)으로 Latest version (0.2.3) of gekko is installed돌아갑니다 . 버전 하위 문자열 만 확인 하지만 모든 패키지를 확인하는 것보다 빠르기 때문에 이것은 최상의 솔루션이 아닐 수 있습니다 . 현재 설치된 버전이 최신 버전 이거나 최신 버전 인 경우 잘못된 값을 반환하므로 가장 안정적인 방법은 아닙니다.TrueFalseif d[name] in s.decode():pip list --outdatedTrue0.2.30.2.300.2.3a . 프로그래밍 방식으로 최신 버전을 얻고 직접 비교하는 것이 개선 될 것입니다.


답변

최신 버전:

내 프로젝트 luddite에는이 기능이 있습니다.

>>> import luddite
>>> luddite.get_version_pypi("gekko")
'0.2.3'

설치된 버전 :

설치된 버전을 확인하는 정식 방법은 __version__최상위 네임 스페이스 의 속성에 액세스하는 것입니다.

>>> import gekko
>>> gekko.__version__
'0.2.0'

불행히도 모든 프로젝트가이 속성을 설정하지는 않습니다. 그렇지 않은 pkg_resources경우 메타 데이터에서 파헤칠 수 있습니다 .

>>> import pkg_resources
>>> pkg_resources.get_distribution("gekko").version
'0.2.0'


답변

이것은 적어도 데모 목적으로 트릭을 수행해야합니다. isLatestVersion확인하려는 패키지 이름으로 전화 하십시오. 중요한 곳을 사용하는 경우 인터넷 액세스가 불가능할 수 있으므로 URL 요청을 시도 / 잡기를 원할 것입니다. 또한 패키지가 설치되지 않은 경우isLatestVersion False를 반환합니다.

Python 3.7.4 및 Pip 19.0.3에서 테스트되었습니다.

import pip
import subprocess
import json
import urllib.request
from pip._internal.operations.freeze import freeze

def isLatestVersion(pkgName):
    # Get the currently installed version
    current_version = ''
    for requirement in freeze(local_only=False):
        pkg = requirement.split('==')
        if pkg[0] == pkgName:
            current_version = pkg[1]

    # Check pypi for the latest version number
    contents = urllib.request.urlopen('https://pypi.org/pypi/'+pkgName+'/json').read()
    data = json.loads(contents)
    latest_version = data['info']['version']

    return latest_version == current_version


답변

PyPI API쿼리하여 간단한 스크립트를 직접 작성하는 것은 어렵지 않습니다 . 최신 Python 3.8에서는 표준 라이브러리 만 사용할 수 있습니다 (Python 3.7 이전 버전을 사용하는 경우 importlib_metadata백 포트 를 설치해야 함 ).

# check_version.py

import json
import urllib.request
import sys

try:
    from importlib.metadata import version
except ImportError:
    from importlib_metadata import version

from distutils.version import LooseVersion


if __name__ == '__main__':
    name = sys.argv[1]
    installed_version = LooseVersion(version(name))

    # fetch package metadata from PyPI
    pypi_url = f'https://pypi.org/pypi/{name}/json'
    response = urllib.request.urlopen(pypi_url).read().decode()
    latest_version = max(LooseVersion(s) for s in json.loads(response)['releases'].keys())

    print('package:', name, 'installed:', installed_version, 'latest:', latest_version)

사용 예 :

$ python check_version.py setuptools
package: setuptools installed: 41.2.0 latest: 41.6.0

설치 한 경우 버전 구문 분석 packagingdistutils.version위한 더 나은 대안입니다 .

from distutils.version import LooseVersion

...

LooseVersion(s)

된다

from packaging.version import parse

...

parse(s)


답변