web-dev-qa-db-fra.com

PEP8 - import pas en haut du fichier avec sys.path

Problème

PEP8 a pour règle de placer les importations en haut d'un fichier:

Les importations sont toujours placées en haut du fichier, juste après les commentaires de module et les docstrings, et avant les globales et les constantes de module.

Cependant, dans certains cas, je pourrais vouloir faire quelque chose comme:

import sys
sys.path.insert("..", 0)

import my_module

Dans ce cas, l'utilitaire de ligne de commande pep8 Signale mon code:

L'importation de module E402 n'est pas en haut du fichier

Quel est le meilleur moyen d’obtenir la conformité PEP8 avec les modifications de sys.path?

Pourquoi

J'ai ce code parce que je suis la structure du projet donné dans Le Guide de l'auto-stoppeur en Python .

Ce guide suggère que j’ai un dossier my_module Distinct du dossier tests, qui se trouvent tous deux dans le même répertoire. Si je veux accéder à my_module À partir de tests, je pense que je dois ajouter .. Au sys.path

53
Luke Taylor

Souvent, j'ai plusieurs fichiers avec des tests dans un sous-répertoire foo/tests de mon projet, alors que les modules que je teste sont dans foo/src. Pour exécuter les tests à partir de foo/tests sans erreur d'importation, je crée un fichier foo/tests/pathmagic.py ça ressemble à ça;

"""Path hack to make tests work."""

import os
import sys

bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
modpath = os.sep.join(bp + ['src'])
sys.path.insert(0, modpath)

Dans chaque fichier de test, j'utilise ensuite

import pathmagic  # noqa

comme la première importation. Le commentaire "noqa" empêche pycodestyle/pep8 de se plaindre d'une importation non utilisée.

36
Roland Smith

S'il n'y a que quelques importations, vous pouvez simplement ignorer PEP8 sur ces lignes import:

import sys
sys.path.insert("..", 0)
import my_module  # noqa: E402
53
astorga

Il existe une autre solution de contournement.

import sys
... all your other imports...

sys.path.insert("..", 0)
try:
    import my_module
except:
    raise
9
Peuchele

Je viens juste de me débattre avec une question similaire, et je pense avoir trouvé une solution légèrement plus intéressante que la réponse acceptée.

Créez un module pathmagic qui effectue la manipulation sys.path, mais apportez la modification dans un gestionnaire de contexte :

"""Path hack to make tests work."""

import os
import sys

class context:
    def __enter__(self):
        bp = os.path.dirname(os.path.realpath('.')).split(os.sep)
        modpath = os.sep.join(bp + ['src'])
        sys.path.insert(0, modpath)

    def __exit__(self, *args):
        pass

Ensuite, dans vos fichiers de test (ou partout où vous en avez besoin), vous effectuez les tâches suivantes:

import pathmagic

with pathmagic.context():
    import my_module
    # ...

De cette manière, flake8/pycodestyle ne se plaint pas, vous n'avez pas besoin de commentaires particuliers et la structure semble avoir du sens.

Pour plus de netteté, envisagez de réellement inverser le chemin dans le __exit__ block, bien que cela puisse causer des problèmes avec les imports paresseux (si vous placez le code du module en dehors du contexte), cela ne vaut peut-être pas la peine.


[~ # ~] edit [~ # ~] : Je viens de voir un truc beaucoup plus simple dans un réponse à une question différente : ajouter assert pathmagic sous vos importations pour éviter le commentaire noqa.

4
itsadok

Avez-vous déjà essayé ce qui suit:

import sys
from importlib import import_module

sys.path.insert("..", 0)

# import module
my_mod = import_module('my_module')

# get method or function from my_mod
my_method = getattr(my_mod , 'my_method')
2
Daniel Lee

Pour vous conformer à pep8, vous devez inclure votre chemin de projet dans le chemin python) afin de pouvoir effectuer des importations relatives/absolues.

Pour ce faire, vous pouvez consulter la réponse suivante: Ajouter définitivement un répertoire à PYTHONPATH

2
Pierre Barre