3. Méthode pip
Dans ce cas, comme il n’y a pas de librairie Python (en tout cas je n’en ai pas trouvée en version 3.12) qui permette de faire la même chose qu’avec importlib, nous utilisons pip directement via une méthode subprocess, il s’agit de la fonction pypkgs_pkg_pip. Dans un premier temps nous lançons pip show et et nous récupérons la sortie standard dans la chaîne de caractères stdout_str :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
# try to use infos using pip try: result = subprocess.run( [sys.executable, "-m", "pip", "show", pname], stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True ) stdout_str = str(result.stdout) stderr_str = str(result.stderr) if (verb > 2): print(stdout_str) except: if (verb > 1): print("!problem with pip or package '%s'" % (pdict['name'])) return pdict if result.returncode != 0 or not result.stdout: if (verb > 1): print("!package '%s' not resolved (pip)" % (pdict['name'])) return pdict |
L’option universal_newlines permet d’utiliser tous les caractères de fin de ligne quel que soit l’OS utilisé.
universal newlines – A manner of interpreting text streams in which all of the following are recognized as ending a line: the Unix end-of-line convention ‘\n’, the Windows convention ‘\r\n’, and the old Macintosh convention ‘\r’. See PEP 278 and PEP 3116, as well as bytes.splitlines() for an additional use.
Nous devons aussi passer la transformation de bytes en string pour utiliser la sortie standard, et que nous transformons en dictionnaire info:
|
1 2 3 4 5 6 7 8 9 10 |
# get infos from 'pip show' info = {} try: for line in result.stdout.splitlines(): if ':' in line: key, value = line.split(':', 1) info[key.strip().lower()] = value.strip() except: if (verb > 1): print("!problem with pip output") return pdict |
Puis nous allons exploiter le dictionnaire info (qui est spécifique au information retournées par pip) pour renseigner le dictionnaire pdict dont les clés sont les mêmes pour toutes les méthodes. Avec pip nous avons accès aux clés ‘name’ (nom du paquetage), ‘loc’ (localisation), ‘ver’ (version), ‘summary’ (résumé de la fonction du paquetage), ‘req’ (dépendances du paquetage), ‘reqby’ (autres paquetages dépendants de celui ci) :
|
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# exploit infos from pip if (len(info) > 0): ## if (pdict['name'] == ''): pdict['name'] = info.get('name') if (pdict['ver'] == ''): pdict['ver'] = info.get('version') if (pdict['loc'] == ''): pdict['loc'] = info.get('location') if (pdict['summary'] == ''): pdict['summary'] = info.get('summary') if (len(pdict['req']) <= 0): s = info.get('requires') s = str_replace(s, ' ', '') words = str_str2vec(s, '', '', ',') pdict['req'] = words if (len(pdict['reqby']) <= 0): s = info.get('required-by') s = str_replace(s, ' ', '') words = str_str2vec(s, '', '', ',') pdict['reqby'] = words else: if (verb > 1): print("!problem with pip output processing") return pdict |
Une fois que c’est fini, un appel à la fonction pypkgs_scoring permet de compléter la valeur de pdict[score] en ajoutant la contribution de pip. Ce qui se fait par la commande pdict = pypkgs_scoring(pdict, what='pip') puis nous renvoyons à nouveau le dictionnaire pdict.
Test drive
La fonction doit être utilisée en complément de la méthode importlib, donc après les fonctions pypkgs_init_pdict et pypkgs_importlib, par exemple (ou pkgname correspond à un nom de paquetage) :
|
1 2 3 4 |
print("-> package [%s]" % (pkgname)) pdict = pypkgs_init_pdictpkgname, pdict, files=True, meta=True, verb=1) pdict = pypkgs_pkg_pip(pkgname, pdict, verb=1) print(pdict) |
Dans le cas de PIL nous n’avons rien de plus par rapport à importlib, le score (identique) est de 160, en fait la méthode refuse le scoring, considérant que toutes les conditions ne sont pas réunies pour faire basculer le bit dédié à PIL.
Dans le cas de pillow nous améliorons le score, de 64 à 80, nous obtenons la localisation, mais celle ci n’est pas très intéressante: 'loc': 'C:\\Python3\\envs\\prod\\Lib\\site-packages'. Notons que nous avons un répertoire pillow-11.3.0.dist-info dans C:\Python3\envs\prod\Lib\site-packages et dans C:\Python3\Lib\site-packages.
Dans le cas de Pillow le résultat est identique à ‘pillow’.
Dans le cas de numpy, nous améliorons le score de 224 à 240, le champ 'reqby' apparait: 'reqby': ['biopandas', 'biopython', 'cftime', 'contourpy', 'matplotlib', ..., 'scikit-learn', 'scipy', 'seaborn', 'statsmodels'].