패키지에서 프로그래밍 방식으로 스크립트의 최신 버전인지 확인하고 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
돌아갑니다 . 버전 하위 문자열 만 확인 하지만 모든 패키지를 확인하는 것보다 빠르기 때문에 이것은 최상의 솔루션이 아닐 수 있습니다 . 현재 설치된 버전이 최신 버전 이거나 최신 버전 인 경우 잘못된 값을 반환하므로 가장 안정적인 방법은 아닙니다.True
False
if d[name] in s.decode():
pip list --outdated
True
0.2.3
0.2.30
0.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
설치 한 경우 버전 구문 분석 packaging
을 distutils.version
위한 더 나은 대안입니다 .
from distutils.version import LooseVersion
...
LooseVersion(s)
된다
from packaging.version import parse
...
parse(s)