2017-09-03 7 views
0

Je travaille sur une bibliothèque Python (pas de moi) qui ressemble à ceci:Comment empaqueter une bibliothèque dont l'importation produit des effets secondaires en Python?

. 
├── README.md 
├── setup.py 
└── library 
    ├── __init__.py 
    ├── core.py 
    ├── a.py 
    └── b.py 

Le fichier __init__.py faire usage de core.py qui utilise lui-même a.py et b.py. La chose importante à noter est que import library a quelques effets secondaires qui sont délibérément destinés.

Cependant, je voudrais donner à l'utilisateur la possibilité d'utiliser les fonctions de core.py sans effets secondaires. Malheureusement, comme vous le savez, import library.core ou from library import core exécutera __init__.py (où des effets secondaires se produisent) de toute façon.

Savez-vous comment j'ai pu réorganiser mon paquet et le setup.py pour résoudre ce problème?


Je pensais à quelque chose comme ceci:

. 
├── README.md 
├── setup.py 
├── library_core 
│ ├── __init__.py 
│ ├── core.py 
│ ├── a.py 
│ └── b.py 
└── library 
    └── __init__.py # Import library_core and apply side effects 

Je setup.py jour avec packages = ['library', 'library_core']. De cette façon, l'importation library ne change rien, mais l'utilisateur peut alors importer library_core sans effets secondaires. De plus, cela éviterait la duplication du code et tout resterait dans le même référentiel.

Malheureusement, cela ne fonctionne pas car je n'ai pas la possibilité d'importer library_core de library car ils ne sont pas au même endroit dans l'arborescence de fichiers.

+0

* « Malheureusement, cela ne fonctionne pas parce que je n'ai pas la possibilité d'importer library_core de la bibliothèque » * - On dirait que c'est votre problème principal, que se passe-t-il lorsque vous essayez 'from library_core import core' dans' library/__ init __. py'? – Kos

+0

@Kos En fait, cela pourrait fonctionner ... J'ai essayé d'abord avec 'de ..library_core import * 'qui a évidemment échoué, mais simplement' import library_core' fonctionnera ** une fois le paquet installé ** avec 'python setup.py install'. Je suppose que c'est la voie à suivre. Donc, je vais vider la question. – Delgan

Répondre

0

L'utilisation de deux paquets semble être le meilleur moyen.

L'utilisation de deux paquets adjacents peut fonctionner que si l'ensemble est installé (avec python setup.py install par exemple). Cela complique considérablement le développement, pour les tests unitaires par exemple: il était alors impossible de faire import library puisque library_core ne pouvait pas être trouvé s'il n'était pas installé. Donc, la meilleure solution est simplement de créer un sous-package, et de spécifier dans le setup.py où se trouve library_core grâce à l'option package_dir.

L'arbre des fichiers ressemblerait à ceci:

. 
├── README.md 
├── setup.py 
└── library 
    ├── __init__.py 
    └── core 
     ├── __init__.py 
     ├── a.py 
     └── b.py 

Et setup.py:

setup(
    name = 'library', 
    packages = ['library', 'library.core', 'library_core'], 
    package_dir = {'library_core': 'library/core'}, 
    ... 
) 
0

Je vous recommande de ne plus vous fier aux effets secondaires et de demander à l'utilisateur de les déclencher explicitement en appelant une fonction documentée. Sinon, vous êtes en train de combattre une bataille perdue: la valeur par défaut est actuellement de déclencher les effets secondaires, et vous devez ensuite les annuler si l'utilisateur n'en veut pas.

+0

Ce n'est pas ma bibliothèque, elle est déjà très populaire donc je n'ai aucun moyen de changer le comportement actuel. – Delgan

+0

Les exceptions communes à la règle sont les bibliothèques polyfill. Comparez et contrastez 'from __future__ import absolute_import'. Mais oui, ce n'est pas pratique, par exemple flake8 se plaindra des importations "inutilisées" – Kos