web-dev-qa-db-fra.com

Comment contourner `exist_ok` manquant sur Python 2.7?

On Python 2.7 os.makedirs() est manquant exist_ok. Ceci est disponible dans Python 3 uniquement).

Je sais que c'est un travail autour:

try:
    os.makedirs(settings.STATIC_ROOT)
except OSError as e:
    if e.errno != errno.EEXIST:
        raise

Je pourrais créer une méthode my_make_dirs() personnalisée et l'utiliser à la place de os.makedirs(), mais ce n'est pas sympa.

Quel est le travail le plus Pythonic autour, si vous avez forcé à prendre en charge Python 2.7?

AFAIK python-future ou six n'aidera pas ici.

19
guettli

Une solution consiste à utiliser pathlib . Il a un backport pour Python 2 et sa fonction mkdir() supporte exist_ok.

try:
  from pathlib import Path
except ImportError:
  from pathlib2 import Path  # python 2 backport

Path(settings.STATIC_ROOT).mkdir(exist_ok=True)
14
kichik

Vous pouvez appeler makedirs () après avoir vérifié que le chemin n'existe pas:

import os

if not os.path.exists(path):
    os.makedirs(path)
9
Pat Myron
def makedirs(name, exist_ok=False):
    if not os.path.exists(name) or not exist_ok:
        os.makedirs(name)
0
crizCraig

Ce que vous faites est probablement correct, mais si vous souhaitez détecter et adapter, vous pouvez effectuer un monkeypatch lors de l'exécution. Je ne dirais pas que c'est la meilleure idée, cela peut entraîner des éventualités étranges, mais selon votre situation, c'est peut-être bien. Au minimum, mettez de la documentation dans et autour de ce code pour que le gars ou la fille suivante sache ce qui se passe.

Voici un exemple de cela - vous pouvez exécuter ce script avec "true" ou autre chose comme argument et voir la différence.

Détectez la version de python en utilisant sys.version_info: https://docs.python.org/2/library/sys.html#sys.version_info - https://docs.python.org/3/library/sys.html#sys.version_info

import sys
import os


def blah(a):
    return "lskdflsdkfj"


if sys.argv[1] == "true":
    os.listdir = blah

print(os.listdir('.'))
0
jimf

La réponse acceptée est incomplète car os.makedirs() crée des sous-dossiers de manière récursive et Path.mkdir(), comme os.mkdir(), ne peut créer qu'un nouveau répertoire dans un emplacement existant. Une autre approche consiste à tirer parti des exceptions levées pour distinguer et tolérer les comportements entre Python2/3.

import errno
import os
import os.path

def makedirs(folder, *args, **kwargs):
  try:
    return os.makedirs(folder, exist_ok=True, *args, **kwargs)
  except TypeError: 
    # Unexpected arguments encountered 
    pass

  try:
    # Should work is TypeError was caused by exist_ok, eg., Py2
    return os.makedirs(folder, *args, **kwargs)
  except OSError as e:
    if e.errno != errno.EEXIST:
      raise

    if os.path.isfile(folder):
      # folder is a file, raise OSError just like os.makedirs() in Py3
      raise

Voir aussi: erreur Python "FileExists" lors de la création du répertoire

0
clifflu