778 votes

Equivalent de la commande shell 'cd' pour changer de répertoire de travail ?

cd est la commande shell permettant de changer le répertoire de travail.

Comment changer le répertoire de travail actuel en Python ?

2 votes

Donc, dans l'interpréteur os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subf‌​older')) - ou ?

2 votes

Intéressant dans ce contexte : Trouver le répertoire courant et le répertoire du fichier : os.getcwd()

872voto

mlabbe Points 2694

Vous pouvez changer le répertoire de travail avec :

import os

os.chdir(path)

Il y a deux bonnes pratiques à suivre lorsque vous utilisez cette méthode :

  1. Attraper l'exception (WindowsError, OSError) sur le chemin invalide. Si l'exception est levée, n'effectuez aucune opération récursive, en particulier les opérations destructives. Elles opéreront sur l'ancien chemin et non sur le nouveau.
  2. Retournez à votre ancien répertoire lorsque vous avez terminé. Ceci peut être fait d'une manière sûre en enveloppant votre appel chdir dans un gestionnaire de contexte, comme Brian M. Hunt a fait dans sa réponse .

La modification du répertoire de travail actuel dans un sous-processus ne modifie pas le répertoire de travail actuel dans le processus parent. Ceci est également vrai pour l'interpréteur Python. Vous ne pouvez pas utiliser os.chdir() pour modifier le CWD du processus d'appel.

4 votes

cdunn2001 Le poids plume de l'entreprise réponse basée sur les décorateurs est l'approche idéale pour le Python moderne. La réponse ci-dessus démontre pourquoi. Ne jamais appeler os.chdir() en dehors d'un gestionnaire de contexte, à moins que tu penses savoir ce que tu fais. ( Vous ne le savez probablement pas. )

6 votes

C'est la méthode la plus simple dans un shell interactif, je pense. Notez que sous Windows, vous devez utiliser des slashs avant, comme os.chdir("C:/path/to/location")

0 votes

La seule chose à savoir est que si vous faites de votre programme python un exécutable et que vous le lancez dans cron, il démarrera dans votre répertoire personnel. Il est donc préférable d'utiliser un chemin entièrement qualifié. Cela fonctionne définitivement, mais j'utilise toujours des chemins entièrement qualifiés dans tout script que je pourrais invoquer à partir de Python parce qu'il n'y a aucune garantie que cela s'appliquera en dehors du programme Python lui-même.

343voto

Brian M. Hunt Points 12506

Voici un exemple de gestionnaire de contexte pour changer le répertoire de travail. Il est plus simple qu'un Version ActiveState dont il est question ailleurs, mais ce document fait l'affaire.

Gestionnaire de contexte : cd

import os

class cd:
    """Context manager for changing the current working directory"""
    def __init__(self, newPath):
        self.newPath = os.path.expanduser(newPath)

    def __enter__(self):
        self.savedPath = os.getcwd()
        os.chdir(self.newPath)

    def __exit__(self, etype, value, traceback):
        os.chdir(self.savedPath)

Ou essayez le équivalent plus concis (ci-dessous) en utilisant ContextManager .

Exemple

import subprocess # just to call an arbitrary command e.g. 'ls'

# enter the directory like this:
with cd("~/Library"):
   # we are in ~/Library
   subprocess.call("ls")

# outside the context manager we are back wherever we started.

4 votes

Si vous avez besoin de savoir à partir de quel répertoire vous avez changé, vous pouvez simplement ajouter return self à la fin de __enter__ . De cette façon, vous pouvez faire with cd('foo') as cm: et accéder au répertoire précédent comme cm.savedPath

0 votes

Notez qu'il existe des cas où le retour à l'ancien répertoire (celui stocké dans "savedPath") n'est pas possible. Par exemple, si un processus plus privilégié exécute un processus moins privilégié, le second processus hérite du répertoire de travail du premier processus, même dans les cas où le second processus ne peut pas entrer dans ce répertoire de travail avec ses propres capacités.

0 votes

Je reçois le message d'avertissement suivant : Attribute 'savedPath' defined outside __init__ [attribute-defined-outside-init]

149voto

Evan Fosmark Points 17732

J'utiliserais os.chdir comme ça :

os.chdir("/path/to/change/to")

Au fait, si vous avez besoin de connaître votre chemin actuel, utilisez os.getcwd() .

Plus de aquí

137voto

cdunn2001 Points 3597

cd() est facile à écrire en utilisant un générateur et un décorateur.

from contextlib import contextmanager
import os

@contextmanager
def cd(newdir):
    prevdir = os.getcwd()
    os.chdir(os.path.expanduser(newdir))
    try:
        yield
    finally:
        os.chdir(prevdir)

Ensuite, le répertoire est rétabli même après l'apparition d'une exception :

os.chdir('/home')

with cd('/tmp'):
    # ...
    raise Exception("There's no place like /home.")
# Directory is now back to '/home'.

3 votes

En outre, notez cette erreur potentielle (pour oublier le try/finally ).

7 votes

Brillance ! Si le commentaire d'introduction du réponse acceptée ont été injectés dans ce ce serait un idéal incommensurable. Néanmoins, l'implémentation concise et sûre en Python de cette réponse justifie tous les votes positifs que j'ai à donner.

3 votes

Pourquoi yield et non return ? C'est censé être un générateur ?

26voto

Brian Clapper Points 11222

Si vous utilisez une version relativement récente de Python, vous pouvez aussi utiliser un gestionnaire de contexte, tel que celui-ci :

from __future__ import with_statement
from grizzled.os import working_directory

with working_directory(path_to_directory):
    # code in here occurs within the directory

# code here is in the original directory

UPDATE

Si vous préférez le faire vous-même :

import os
from contextlib import contextmanager

@contextmanager
def working_directory(directory):
    owd = os.getcwd()
    try:
        os.chdir(directory)
        yield directory
    finally:
        os.chdir(owd)

1 votes

Bonne idée générale. Voici une Recette d'Activestate sans autres dépendances.

4 votes

Les dépendances sont mauvaises. La fonction intégrée de Python contextlib.contextmanager Le décorateur est bon. Voir cdunn2001 's réponse basée sur les décorateurs ce qui serait idéalement la réponse acceptée aujourd'hui.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X