25개 이상의 토픽을 선택하실 수 없습니다. Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
This repo is archived. You can view files and clone it, but cannot push or open issues/pull-requests.

03-bibliotheques-tierces.rst 9.3 KiB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. Bibliothèques tierces
  2. =====================
  3. Prenons un exemple::
  4. # dans foo.py
  5. import tabulate
  6. scores = [
  7. ["John", 345],
  8. ["Mary-Jane", 2],
  9. ["Bob", 543],
  10. ]
  11. table = tabulate.tabulate(scores)
  12. print(table)
  13. .. code-block:: console
  14. $ python3 foo.py
  15. --------- ---
  16. John 345
  17. Mary-Jane 2
  18. Bob 543
  19. --------- ---
  20. Ici, le module ``tabulate`` n'est ni dans la bibliothèque standard, ni écrit par l'auteur du script ``foo.py``. On dit que c'est une bibliothèque tierce.
  21. On peut trouver `le code source de tabulate
  22. <https://bitbucket.org/astanin/python-tabulate/src/master/>`_ facilement. La
  23. question qui se pose alors est: comment faire en sorte que `sys.path`
  24. contienne le module ``tabulate``?
  25. Eh bien, plusieurs solutions s'offrent à vous.
  26. Le gestionnaire de paquets
  27. ---------------------------
  28. Si vous utilisez une distribution Linux, peut-être pourrez-vous utiliser votre gestionnaire de paquets:
  29. .. code-block:: console
  30. $ sudo apt install python3-tabulate
  31. Comme vous lancez votre gestionnaire de paquets avec ``sudo``, celui-ci sera capable d'écrire dans les chemins système de ``sys.path``.
  32. À la main
  33. ----------
  34. Une autre méthode consiste à partir des sources - par exemple, si le paquet de votre distribution n'est pas assez récent, ou si vous avez besoin de modifier le code de la bibliothèque en question.
  35. Voici une marche à suivre possible :
  36. 1. Récupérer les sources de la version qui vous intéresse dans la `section téléchargement de bitbucket <https://bitbucket.org/astanin/python-tabulate/downloads/?tab=tags>`_.
  37. 1. Extraire l'archive, par exemple dans ``src/tabulate``
  38. 1. Se rendre dans ``src/tabulate`` et lancer ``python3 setup.py install --user``
  39. Anatomie du fichier setup.py
  40. -----------------------------
  41. La plupart des bibliothèques Python contiennent un ``setup.py`` à
  42. la racine de leurs sources. Il sert à plein de choses, la commande ``install``
  43. n'étant qu'une parmi d'autres.
  44. Le fichier ``setup.py`` contient en général simplement un ``import`` de
  45. ``setuptools``, et un appel à la fonction ``setup()``, avec de nombreux
  46. arguments::
  47. # tabulate/setup.py
  48. from setuptools import setup
  49. setup(
  50. name='tabulate',
  51. version='0.8.1',
  52. description='Pretty-print tabular data',
  53. py_modules=["tabulate"],
  54. scripts=["bin/tabulate"],
  55. ...
  56. )
  57. Résultat de l'invocation de setup.py
  58. -------------------------------------
  59. Par défaut, ``setup.py`` essaiera d'écrire dans un des chemins système de
  60. ``sys.path``, d'où l'utilisation de l'option ``--user``.
  61. Voici à quoi ressemble la sortie de la commande:
  62. .. code-block:: console
  63. $ cd src/tabulate
  64. $ python3 setup.py install --user
  65. running install
  66. ...
  67. Copying tabulate-0.8.4-py3.7.egg to /home/dmerej/.local/lib/python3.7/site-packages
  68. ...
  69. Installing tabulate script to /home/dmerej/.local/bin
  70. Notez que module a été copié dans ``~/.local/lib/python3.7/site-packages/``
  71. et le script dans ``~/.local/bin``. Cela signifie que *tous* les scripts Python
  72. lancés par l'utilisateur courant auront accès au module ``tabulate``.
  73. Notez également qu'un script a été installé dans ``~/.local/bin`` - Une
  74. bibliothèque Python peut contenir aussi bien des modules que des scripts.
  75. Un point important est que vous n'avez en général pas besoin de lancer le
  76. script directement. Vous pouvez utiliser ``python3 -m tabulate``. Procéder
  77. de cette façon est intéressant puisque vous n'avez pas à vous soucier de
  78. rajouter le chemin d'installation des scripts dans la variable d'environnement
  79. PATH.
  80. Dépendances
  81. -----------
  82. Prenons une autre bibliothèque : ``cli-ui``.
  83. Elle permet d'afficher du texte en couleur dans un terminal::
  84. import cli_ui
  85. cli_ui.info("Ceci est en", cli_ui.red, "rouge")
  86. Elle permet également d'afficher des tableaux en couleur::
  87. headers=["name", "score"]
  88. data = [
  89. [(bold, "John"), (green, 10.0)],
  90. [(bold, "Jane"), (green, 5.0)],
  91. ]
  92. cli_ui.info_table(data, headers=headers)
  93. Pour ce faire, elle repose sur la bibliothèque ``tabulate`` vue
  94. précédemment. On dit que ``cli-ui`` *dépend* de ``tabulate``.
  95. Déclaration des dépendances
  96. ----------------------------
  97. La déclaration de la dépendance de ``cli-ui`` vers ``tabulate`` s'effectue également dans le fichier ``setup.py``::
  98. setup(
  99. name="cli-ui",
  100. version="0.9.1",
  101. install_requires=[
  102. "tabulate",
  103. ...
  104. ],
  105. ...
  106. )
  107. pypi.org
  108. ---------
  109. On comprend dès lors qu'il doit nécessairement exister un *annuaire* permettant de relier les noms de dépendances à leur code source.
  110. Cet annuaire, c'est le site `pypi.org <https://pypi.org/>`_. Vous y trouverez
  111. les pages correspondant à `tabulate <https://pypi.org/project/tabulate/>`_
  112. et `cli-ui <https://pypi.org/project/python-cli-ui/>`_.
  113. pip
  114. ---
  115. ``pip`` est un outil qui vient par défaut avec Python3[^4]. Vous pouvez également l'installer grâce au script `get-pip.py <https://bootstrap.pypa.io/get-pip.py>`_, en lançant ``python3 get-pip.py --user``.
  116. Il est conseillé de *toujours* lancer ``pip`` avec ``python3 -m pip``. De cette
  117. façon, vous êtes certains d'utiliser le module ``pip`` correspondant à votre
  118. binaire ``python3``, et vous ne dépendez pas de ce qu'il y a dans votre ``PATH``.
  119. ``pip`` est capable d'interroger le site ``pypi.org`` pour retrouver les
  120. dépendances, et également de lancer les différents scripts ``setup.py``.
  121. Comme de nombreux outils, il s'utilise à l'aide de *commandes*. Voici
  122. comment installer ``cli-ui`` à l'aide de la commande 'install' de ``pip``:
  123. .. code-block:: console
  124. $ python3 -m pip install cli-ui --user
  125. Collecting cli-ui
  126. ...
  127. Requirement already satisfied: unidecode in /usr/lib/python3.7/site-packages (from cli-ui) (1.0.23)
  128. Requirement already satisfied: colorama in /usr/lib/python3.7/site-packages (from cli-ui) (0.4.1)
  129. Requirement already satisfied: tabulate in /mnt/data/dmerej/src/python-tabulate (from cli-ui) (0.8.4)
  130. Installing collected packages: cli-ui
  131. Successfully installed cli-ui-0.9.1
  132. On constate ici quelques limitations de ``pip``:
  133. * Il faut penser à utiliser ``--user`` (de la même façon que lorsqu'on lance ``setup.py`` à la main)
  134. * Si le paquet est déjà installé dans le système, pip ne saura pas le
  135. mettre à jour - il faudra passer par le gestionnaire de paquet de
  136. la distribution
  137. En revanche, `pip` contient de nombreuses fonctionnalités intéressantes:
  138. * Il est capable de désinstaller des bibliothèques (à condition toutefois
  139. qu'elles ne soient pas dans un répertoire système)
  140. * Il est aussi capable d'afficher la liste complète des bibliothèques
  141. Python accessibles par l'utilisateur courant avec `freeze`.
  142. Voici un extrait de la commande ``python3 -m pip freeze`` au moment de la rédaction de cet article sur ma machine:
  143. .. code-block:: console
  144. $ python3 -m pip freeze
  145. apipkg==1.5
  146. cli-ui==0.9.1
  147. gaupol==1.5
  148. tabulate==0.8.4
  149. On y retrouve les bibliothèques ``cli-ui`` et ``tabulate``, bien sûr, mais
  150. aussi la bibliothèque ``gaupol``, qui correspond au [programme d'édition de
  151. sous-titres](https://otsaloma.io/gaupol/) que j'ai installé à l'aide du
  152. gestionnaire de paquets de ma distribution. Précisons que les modules de
  153. la bibliothèque standard et ceux utilisés directement par pip sont omis
  154. de la liste.
  155. On constate également que chaque bibliothèque possède un *numéro de version*.
  156. Numéros de version
  157. -------------------
  158. Les numéros de version remplissent plusieurs rôles, mais l'un des principaux
  159. est de spécifier des changements incompatibles.
  160. Par exemple, pour ``cli-ui``, la façon d'appeler la fonction ``ask_choice``
  161. a changé entre les versions 0.7 et 0.8, comme le montre cet extrait du
  162. `changelog <https://tankerhq.github.io/python-cli-ui/changelog.html#v0-8-0)>`_:
  163. *The list of choices used by ask_choice is now a named keyword argument:*
  164. .. code-block::
  165. # Old (<= 0.7)
  166. ask_choice("select a fruit", ["apple", "banana"])
  167. # New (>= 0.8)
  168. ask_choice("select a fruit", choices=["apple", "banana"])
  169. Ceci s'appelle un *changement d'API*.
  170. Réagir aux changements d'API
  171. -----------------------------
  172. Plusieurs possibilités:
  173. * On peut bien sûr adapter le code pour utiliser la nouvelle API, mais cela
  174. n'est pas toujours possible ni souhaitable.
  175. * Une autre solution est de spécifier des *contraintes* sur le numéro de
  176. version dans la déclaration des dépendances. Par exemple::
  177. setup(
  178. install_requires=[
  179. "cli-ui < 0.8",
  180. ...
  181. ]
  182. )
  183. Aparté : pourquoi éviter sudo pip
  184. ---------------------------------
  185. Souvenez-vous que les fichiers systèmes sont contrôlés par votre gestionnaire de paquets.
  186. Les mainteneurs de votre distribution font en sorte qu'ils fonctionnent bien les uns
  187. avec les autres. Par exemple, le paquet ``python3-cli-ui`` ne sera mis à jour
  188. que lorsque tous les paquets qui en dépendent seront prêts à utiliser la
  189. nouvelle API.
  190. En revanche, si vous lancez ``sudo pip`` (où ``pip`` avec un compte root),
  191. vous allez écrire dans ces mêmes répertoire et vous risquez de "casser"
  192. certains programmes de votre système.
  193. Mais il y a un autre problème encore pire.
  194. Conflit de dépendances
  195. ----------------------
  196. Supposons deux projets A et B dans votre répertoire personnel. Ils dépendent
  197. tous les deux de ``cli-ui``, mais l'un des deux utilise ``cli-ui 0.7`` et l'autre
  198. ``cli-ui 0.9``. Que faire ?