Est-il acceptable d'utiliser des tirets dans les fichiers Python lorsque vous essayez de les importer?

149

Fondamentalement, quand j'ai un fichier python comme:

python-code.py

et utilise:

import (python-code)

l'interpréteur me donne une erreur de syntaxe.

Des idées pour y remédier? Les tirets sont-ils illégaux dans les noms de fichiers Python?

Joan Venge
la source

Réponses:

168

Vous devriez consulter PEP 8 , le guide de style pour le code Python:

Noms de package et de module Les modules doivent avoir des noms courts, entièrement en minuscules. Des traits de soulignement peuvent être utilisés dans le nom du module si cela améliore la lisibilité. Les packages Python doivent également avoir des noms courts, entièrement en minuscules, bien que l'utilisation de traits de soulignement soit déconseillée.

Puisque les noms de module sont mappés aux noms de fichiers et que certains systèmes de fichiers sont insensibles à la casse et tronquent les noms longs, il est important que les noms de module soient choisis pour être assez courts - ce ne sera pas un problème sous Unix, mais cela peut être un problème lorsque le code est transporté vers d'anciennes versions Mac ou Windows, ou DOS.

En d'autres termes: renommez votre fichier :)

Paolo Bergantino
la source
75
le problème n'a rien à voir avec le style, c'est une erreur de syntaxe
4
Comme indiqué ci-dessous, il est possible d'avoir toujours un fichier avec ce nom, le guide de style est donc très pertinent.
Paolo Bergantino
5
Il peut être très utile d'utiliser des traits d'union dans le répertoire Python et les noms de fichiers lorsque vous souhaitez explicitement empêcher les importations. Par exemple, dans (disons) un projet Django, vous pouvez avoir des scripts écrits en Python qui ne devraient pas être adressables en tant qu'applications. Vous pouvez les mettre dans un dossier comme ops-scriptset savoir qu'ils ne peuvent pas être importés en utilisant une approche d'espace de noms de package normale. Ou un seul script pourrait être nommé stop-website.pypour un effet similaire. N'importe lequel de ceux-ci pourrait toujours être importé via runpyet d'autres méthodes bien sûr, mais cela permet d'éviter certaines erreurs courantes.
Chris Johnson
Renommer un module peut être problématique, surtout si vous vous appuyez sur une autre norme. Dans mon cas, j'utilise des fichiers cgi python dans le cgi-bindossier (en faisant des tests unitt sur eux), ce qui est assez standard. Sauf si vous avez un cas rare comme celui-ci, renommez définitivement votre module si vous en avez le contrôle.
NuclearPeon
1
Je viens de découvrir que PyDev autorisera les noms de répertoire avec des traits d'union, mais n'affichera pas les classes et / ou les variables internes dans les fichiers .py contenus dans ce répertoire.
user5920660
123

Une autre chose à noter dans votre code est que l'importation n'est pas une fonction. Il import(python-code)devrait en être de même import python-codequi, comme certains l'ont déjà mentionné, est interprété comme "importer du code python moins", pas ce que vous vouliez. Si vous avez vraiment besoin d'importer un fichier avec un tiret dans son nom, vous pouvez faire ce qui suit:

python_code = __import__('python-code')

Mais, comme mentionné ci-dessus, ce n'est pas vraiment recommandé. Vous devriez changer le nom du fichier si c'est quelque chose que vous contrôlez.

Rick Copeland
la source
@KevinAudleman avez-vous un exemple de travail d'utilisation de la bibliothèque d'importation avec un fichier avec trait d'union? J'ai essayé et j'ai échoué.
Tom Hale
@TomHale importlib.import_module ('abmodule-1') devrait fonctionner. Si votre import_module ne fonctionne pas, je pense qu'une importation normale ne fonctionnera pas non plus.
Ian Lin
64

TLDR

Les tirets ne sont pas illégaux mais vous ne devez pas les utiliser pour 3 raisons:

  1. Vous avez besoin d'une syntaxe spéciale pour importer des fichiers avec des tirets
  2. Personne n'attend un nom de module avec un tiret
  3. C'est contre les recommandations du guide de style Python

Si vous devez absolument importer un nom de fichier avec un tiret, la syntaxe spéciale est la suivante:

module_name = __import__('module-name')

Curieux de savoir pourquoi nous avons besoin d'une syntaxe spéciale?

La raison de la syntaxe spéciale est que lorsque vous écrivez, import somenamevous créez un objet module avec un identificateur somename(vous pourrez donc l'utiliser plus tard avec par exemple somename.funcname). Bien sûrmodule-name n'est pas un identifiant valide et donc la syntaxe spéciale qui en donne un valide.

Vous ne comprenez pas pourquoi le nom du module n'est pas un identifiant valide?

Ne vous inquiétez pas, moi non plus. Voici une astuce pour vous aider: Regardez cette ligne python:x=var1-var2 . Voyez-vous une soustraction sur le côté droit de l'affectation ou un nom de variable avec un tiret?

PS

Rien d'original dans ma réponse, sauf d'inclure ce que je considérais comme les informations les plus pertinentes de toutes les autres réponses en un seul endroit

ndemou
la source
J'essaie d'utiliser cette importation d'un package pip avec un trait d'union. psycopg2_binary = import_module('psycopg2-binary'). Erreur => ModuleNotFoundError: No module named 'psycopg2-binary'. Mais psycopg2-binaryest installé. Je ne sais pas comment l'inclure.
Mote Zart
C'est peut-être un problème de chemin. Regardez chrisyeh96.github.io/2017/08/08/…
ndemou
32

Le problème est que ce python-coden'est pas un identifiant. L'analyseur voit cela comme pythonmoins code. Bien sûr, cela ne fera pas ce que vous demandez. Vous devrez utiliser un nom de fichier qui est également un identifiant Python valide. Essayez de remplacer le -par un trait de soulignement.

SingleNegationElimination
la source
4
+1. Je n'ai jamais pensé que le nom de fichier du code source Python devrait être un identifiant valide, car le nom de fichier sera utilisé pour faire référence à l'objet module.
andy
5

Vous pourriez probablement l'importer via un __import__piratage, mais si vous ne savez pas déjà comment, vous ne devriez pas. Les noms de module Python doivent être des noms de variables valides ("identificateurs") - cela signifie que si vous avez un module foo_bar, vous pouvez l'utiliser depuis Python ( print foo_bar). Vous ne pourriez pas le faire avec un nom étrange ( print foo-bar-> erreur de syntaxe).

John Millikin
la source
5

Sur Python 3, utilisez import_module :

from importlib import import_module
python_code = import_module('python-code')

Plus généralement,

import_module('package.subpackage.module')
e18r
la source
1

Bien python-codequ'un nom de fichier approprié soit la meilleure solution, si ce n'est pas sous notre contrôle, un piratage __import__est préférable à la copie, au changement de nom ou à la manipulation du code d'autres auteurs. Cependant, j'ai essayé et cela n'a pas fonctionné sauf si j'ai renommé le fichier en ajoutant l' .pyextension. Après avoir regardé la documentation pour savoir comment obtenir une description .py, je me suis retrouvé avec ceci:

import imp

try:
    python_code_file = open("python-code")
    python_code = imp.load_module('python_code', python_code_file, './python-code', ('.py', 'U', 1))
finally:
    python_code_file.close()

Il a créé un nouveau fichier python-codeclors de la première exécution.

Ale
la source