Bei Verwendung dieser Methode sind zwei bewährte Methoden zu beachten:
Fangen Sie die Ausnahme (WindowsError, OSError) auf einem ungültigen Pfad ab. Wenn die Ausnahme ausgelöst wird, führen Sie keine rekursiven Operationen aus, insbesondere keine destruktiven. Sie werden auf dem alten und nicht auf dem neuen Weg operieren.
Kehren Sie zu Ihrem alten Verzeichnis zurück, wenn Sie fertig sind. Dies kann auf ausnahmesichere Weise erfolgen, indem Sie Ihren chdir-Aufruf in einen Kontextmanager einbinden, wie es Brian M. Hunt in seiner Antwort getan hat .
Durch Ändern des aktuellen Arbeitsverzeichnisses in einem Unterprozess wird das aktuelle Arbeitsverzeichnis im übergeordneten Prozess nicht geändert. Dies gilt auch für den Python-Interpreter. Sie können os.chdir()die CWD des aufrufenden Prozesses nicht ändern.
cdunn2001 ‚s leichte Dekorateur-basierte Antwort ist der ideale Ansatz für modernen Python. Die obige Antwort zeigt warum. Rufen Sie niemals os.chdir()außerhalb eines Kontextmanagers an, es sei denn, Sie glauben zu wissen, was Sie tun. ( Sie wahrscheinlich nicht. )
Cecil Curry
6
Ich denke, dies ist der einfachste Weg in einer interaktiven Shell. Beachten Sie, dass Sie in Windows Schrägstriche verwenden müssen, wieos.chdir("C:/path/to/location")
Josiah
Beachten Sie, dass Ihr Python-Programm, wenn Sie es zu einer ausführbaren Datei machen und in cron ausführen, in Ihrem Home-Verzeichnis gestartet wird. Verwenden Sie daher am besten einen vollständig qualifizierten Pfad. Dies funktioniert definitiv, aber ich verwende immer noch vollqualifizierte Pfade in jedem Skript, das ich von Python aus aufrufen kann, da es keine Garantie gibt, dass dies außerhalb des Python-Programms selbst gilt.
SDsolar
310
Hier ist ein Beispiel eines Kontextmanagers zum Ändern des Arbeitsverzeichnisses. Es ist einfacher als eine ActiveState-Version, auf die an anderer Stelle verwiesen wird, aber dies erledigt den Job.
Kontextmanager: cd
import osclass 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)
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.
Wenn Sie jemals wissen müssen, von welchem Verzeichnis Sie geändert haben, können Sie es einfach return selfam Ende von hinzufügen __enter__. Auf diese Weise können Sie with cd('foo') as cm:auf das vorherige Verzeichnis zugreifencm.savedPath
Sam F
Beachten Sie, dass es Fälle gibt, in denen die Rückkehr zum alten Verzeichnis (das in "savedPath" gespeicherte) nicht möglich ist. Wenn beispielsweise ein Prozess mit mehr Berechtigungen einen Prozess mit weniger Berechtigungen ausführt, erbt der zweite Prozess das Arbeitsverzeichnis des ersten Prozesses, selbst in den Fällen, in denen der zweite Prozess dieses Arbeitsverzeichnis nicht mit eigenen Funktionen eingeben kann.
Kai Petzke
140
Ich würde so verwenden os.chdir:
os.chdir("/path/to/change/to")
Übrigens, wenn Sie Ihren aktuellen Pfad herausfinden müssen, verwenden Sie os.getcwd().
Brillanz! Wenn der einleitende Kommentar aus der akzeptierten Antwort in diese Antwort eingefügt würde, wäre dies unermesslich ideal. Die prägnante, Pythonisch sichere Implementierung dieser Antwort garantiert jedoch alle positiven Stimmen, die ich abgeben muss.
Cecil Curry
3
Warum yieldund nicht return? Soll das ein Generator sein?
EKons
Bitte kommentieren Sie die Relevanz von Rendite und Rendite!
NicoBerrogorry
1
@NicoBerrogorry, es ist ein Generator. Siehe Dokumente zu contextlib.contextmanager . Dies ist ein sehr nützliches Muster in Python, das es wert ist, gelernt zu werden.
cdunn2001
25
Wenn Sie eine relativ neue Version von Python verwenden, können Sie auch einen Kontext - Manager, wie nutzen diese :
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
AKTUALISIEREN
Wenn Sie es vorziehen, Ihre eigenen zu rollen:
import os
from contextlib import contextmanager
@contextmanagerdef working_directory(directory):
owd = os.getcwd()try:
os.chdir(directory)yield directory
finally:
os.chdir(owd)
Gute allgemeine Idee. Hier ein Activestate-Rezept ohne andere Abhängigkeiten.
cfi
4
Abhängigkeiten sind schlecht. Pythons eingebauter contextlib.contextmanagerDekorateur ist gut. Siehe cdunn2001 ‚s Dekorateur basierte Antwort , die idealerweise die akzeptierte Antwort jetzt sein würde.
Cecil Curry
14
Wie bereits von anderen erwähnt, ändern alle oben genannten Lösungen nur das Arbeitsverzeichnis des aktuellen Prozesses. Dies geht verloren, wenn Sie zur Unix-Shell zurückkehren. Wenn Sie verzweifelt sind, können Sie das übergeordnete Shell-Verzeichnis unter Unix mit diesem schrecklichen Hack ändern:
def quote_against_shell_expansion(s):import pipes
return pipes.quote(s)def put_text_back_into_terminal_input_buffer(text):# use of this means that it only works in an interactive session# (and if the user types while it runs they could insert characters between the characters in 'text'!)import fcntl, termios
for c in text:
fcntl.ioctl(1, termios.TIOCSTI, c)def change_parent_process_directory(dest):# the horror
put_text_back_into_terminal_input_buffer("cd "+quote_against_shell_expansion(dest)+"\n")
Wahnsinniger, fragiler Hack bekommt obligatorische Upvotes. Niemand sollte dies jemals tun, insbesondere mit dem Vorbehalt "und wenn der Benutzer tippt, während er läuft ...". Dennoch kitzelt er das Neckbeard Rebell in mir , dass die Eltern CWD zu ändern , um zu sehen ist sorten der aber nicht wirklich möglich. Upvotes! Upvotes für alle!
import os
abs_path ='C://a/b/c'
rel_path ='./folder'
os.chdir(abs_path)
os.chdir(rel_path)
Sie können beide mit os.chdir (abs_path) oder os.chdir (rel_path) verwenden. Sie müssen os.getcwd () nicht aufrufen, um einen relativen Pfad zu verwenden.
Wenn Sie die Option "cd .." ausführen möchten, geben Sie einfach Folgendes ein:
os.chdir ("..")
es ist das gleiche wie in Windows cmd: cd .. Natürlich ist der Import von Betriebssystemen erforderlich (z. B. geben Sie es als erste Zeile Ihres Codes ein)
Wenn Sie spyder und love GUI verwenden, können Sie einfach auf die Ordnerschaltfläche in der oberen rechten Ecke Ihres Bildschirms klicken und durch die Ordner / Verzeichnisse navigieren, die Sie als aktuelles Verzeichnis wünschen. Anschließend können Sie in der Spyder-IDE zur Registerkarte "Datei-Explorer" des Fensters wechseln und alle dort vorhandenen Dateien / Ordner anzeigen. Um Ihr aktuelles Arbeitsverzeichnis zu überprüfen, gehen Sie zur Konsole von Spyder IDE und geben Sie einfach ein
pwd
Es wird derselbe Pfad gedruckt, den Sie zuvor ausgewählt haben.
Das Ändern des aktuellen Verzeichnisses des Skriptprozesses ist trivial. Ich denke, die Frage ist tatsächlich, wie man das aktuelle Verzeichnis des Befehlsfensters ändert, von dem aus ein Python-Skript aufgerufen wird, was sehr schwierig ist. Ein Bat-Skript in Windows oder ein Bash-Skript in einer Bash-Shell kann dies mit einem normalen CD-Befehl tun, da die Shell selbst der Interpreter ist. Sowohl unter Windows als auch unter Linux ist Python ein Programm, und kein Programm kann die Umgebung seiner Eltern direkt ändern. Die Kombination eines einfachen Shell-Skripts mit einem Python-Skript, das die meisten harten Aufgaben erledigt, kann jedoch das gewünschte Ergebnis erzielen. Um beispielsweise einen erweiterten CD-Befehl mit Durchlaufverlauf für Rückwärts- / Vorwärts- / Auswahl-Revisit zu erstellen, habe ich ein relativ komplexes Python-Skript geschrieben, das von einem einfachen Bat-Skript aufgerufen wird. Die Durchlaufliste wird in einer Datei gespeichert. mit dem Zielverzeichnis in der ersten Zeile. Wenn das Python-Skript zurückkehrt, liest das Bat-Skript die erste Zeile der Datei und macht es zum Argument für cd. Das vollständige Fledermaus-Skript (aus Gründen der Kürze minus Kommentare) lautet:
if _%1== _. goto cdDone
if _%1== _? goto help
if/i _%1 NEQ _-H goto doCd
:help
echo d.bat and dSup.py 2016.03.05.Extended chdir.
echo -C = clear traversal list.
echo -B or nothing = backward (to previous dir).
echo -F or-= forward (to next dir).
echo -R = remove current from list andreturn to previous.
echo -S = select from list.
echo -H,-h,?= help.
echo .= make window title current directory.
echo Anythingelse= target directory.
goto done
:doCd
%~dp0dSup.py %1for/F %%d in(%~dp0dSupList )do(
cd %%d
if errorlevel 1(%~dp0dSup.py -R )
goto cdDone
):cdDone
title %CD%:done
Das Python-Skript dSup.py lautet:
import sys, os, msvcrt
def indexNoCase ( slist, s ):for idx in range( len( slist )):if slist[idx].upper()== s.upper():return idx
raiseValueError# .........main process ...................if len( sys.argv )<2:
cmd =1# No argument defaults to -B, the most common operationelif sys.argv[1][0]=='-':if len(sys.argv[1])==1:
cmd =2# '-' alone defaults to -F, second most common operation.else:
cmd ='CBFRS'.find( sys.argv[1][1:2].upper())else:
cmd =-1
dir = os.path.abspath( sys.argv[1])+'\n'# cmd is -1 = path, 0 = C, 1 = B, 2 = F, 3 = R, 4 = S
fo = open( os.path.dirname( sys.argv[0])+'\\dSupList', mode ='a+t')
fo.seek(0)
dlist = fo.readlines(-1)if len( dlist )==0:
dlist.append( os.getcwd()+'\n')# Prime new directory list with current.if cmd ==1:# B: move backward, i.e. to previous
target = dlist.pop(0)
dlist.append( target )elif cmd ==2:# F: move forward, i.e. to next
target = dlist.pop( len( dlist )-1)
dlist.insert(0, target )elif cmd ==3:# R: remove current from list. This forces cd to previous, a# desireable side-effect
dlist.pop(0)elif cmd ==4:# S: select from list# The current directory (dlist[0]) is included essentially as ESC.for idx in range( len( dlist )):print('('+ str( idx )+')', dlist[ idx ][:-1])whileTrue:
inp = msvcrt.getche()if inp.isdigit():
inp = int( inp )if inp < len( dlist ):print('')# Print the newline we didn't get from getche.breakprint(' is out of range')# Select 0 means the current directory and the list is not changed. Otherwise# the selected directory is moved to the top of the list. This can be done by# either rotating the whole list until the selection is at the head or pop it# and insert it to 0. It isn't obvious which would be better for the user but# since pop-insert is simpler, it is used.if inp >0:
dlist.insert(0, dlist.pop( inp ))elif cmd ==-1:# -1: dir is the requested new directory.# If it is already in the list then remove it before inserting it at the head.# This takes care of both the common case of it having been recently visited# and the less common case of user mistakenly requesting current, in which# case it is already at the head. Deleting and putting it back is a trivial# inefficiency.try:
dlist.pop( indexNoCase( dlist, dir ))exceptValueError:pass
dlist = dlist[:9]# Control list length by removing older dirs (should be# no more than one).
dlist.insert(0, dir )
fo.truncate(0)if cmd !=0:# C: clear the list
fo.writelines( dlist )
fo.close()
exit(0)
Obwohl es eine nette Antwort ist, hat das OP eine Antwort ausgewählt, die besagt, dass es nicht darum geht, die CWD des übergeordneten Prozesses zu ändern. Das klärt mögliche Unklarheiten darüber auf, was die Frage bedeutet.
der Blechmann
An Tin Man - diese Antwort wurde ausgewählt, bevor ich meinen Vorschlag veröffentlichte. Ich denke, dass die weitreichenden Antworten verwirrend gewesen sein könnten. CD innerhalb eines bestimmten Prozesses (dh eines Python-Skripts) ist so einfach, dass ich nicht weiß, warum jemand danach fragen würde.
David McCracken
1
Eigentlich wurde diese Antwort vor Jahren ausgewählt . Wenn es nicht angemessen wäre, wäre es seitdem oft gerufen worden.
der Blechmann
Ich denke, dass Verwirrung bleibt. In jüngerer Zeit wurde die Frage "Simulieren des Linux-Befehls" cd "in Python und Beibehalten der Verzeichnisänderung nach dem Beenden des Programms [duplizieren]" als hier beantwortet abgetan, aber tatsächlich wird diese Frage von der ausgewählten Antwort nicht behandelt. Mein Vorschlag ist für Windows, aber die Probleme sind unter Linux dieselben.
os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subfolder'))
- oder?os.getcwd()
Antworten:
Sie können das Arbeitsverzeichnis ändern mit:
Bei Verwendung dieser Methode sind zwei bewährte Methoden zu beachten:
Durch Ändern des aktuellen Arbeitsverzeichnisses in einem Unterprozess wird das aktuelle Arbeitsverzeichnis im übergeordneten Prozess nicht geändert. Dies gilt auch für den Python-Interpreter. Sie können
os.chdir()
die CWD des aufrufenden Prozesses nicht ändern.quelle
os.chdir()
außerhalb eines Kontextmanagers an, es sei denn, Sie glauben zu wissen, was Sie tun. ( Sie wahrscheinlich nicht. )os.chdir("C:/path/to/location")
Hier ist ein Beispiel eines Kontextmanagers zum Ändern des Arbeitsverzeichnisses. Es ist einfacher als eine ActiveState-Version, auf die an anderer Stelle verwiesen wird, aber dies erledigt den Job.
Kontextmanager:
cd
Oder probieren Sie mit ContextManager das präzisere Äquivalent ( siehe unten) .
Beispiel
quelle
return self
am Ende von hinzufügen__enter__
. Auf diese Weise können Siewith cd('foo') as cm:
auf das vorherige Verzeichnis zugreifencm.savedPath
Ich würde so verwenden
os.chdir
:Übrigens, wenn Sie Ihren aktuellen Pfad herausfinden müssen, verwenden Sie
os.getcwd()
.Mehr hier
quelle
cd()
ist einfach mit einem Generator und einem Dekorateur zu schreiben.Dann wird das Verzeichnis auch nach dem Auslösen einer Ausnahme zurückgesetzt:
quelle
try/finally
).yield
und nichtreturn
? Soll das ein Generator sein?Wenn Sie eine relativ neue Version von Python verwenden, können Sie auch einen Kontext - Manager, wie nutzen diese :
AKTUALISIEREN
Wenn Sie es vorziehen, Ihre eigenen zu rollen:
quelle
contextlib.contextmanager
Dekorateur ist gut. Siehe cdunn2001 ‚s Dekorateur basierte Antwort , die idealerweise die akzeptierte Antwort jetzt sein würde.Wie bereits von anderen erwähnt, ändern alle oben genannten Lösungen nur das Arbeitsverzeichnis des aktuellen Prozesses. Dies geht verloren, wenn Sie zur Unix-Shell zurückkehren. Wenn Sie verzweifelt sind, können Sie das übergeordnete Shell-Verzeichnis unter Unix mit diesem schrecklichen Hack ändern:
quelle
os.chdir()
ist der richtige Weg.quelle
os.chdir()
ist die pythonische Version voncd
.quelle
Sie können beide mit os.chdir (abs_path) oder os.chdir (rel_path) verwenden. Sie müssen os.getcwd () nicht aufrufen, um einen relativen Pfad zu verwenden.
quelle
Weiter in Richtung von Brian hervorgehoben und basierend auf sh (1.0.8+)
quelle
Wenn Sie die Option "cd .." ausführen möchten, geben Sie einfach Folgendes ein:
os.chdir ("..")
es ist das gleiche wie in Windows cmd: cd .. Natürlich ist der Import von Betriebssystemen erforderlich (z. B. geben Sie es als erste Zeile Ihres Codes ein)
quelle
Wenn Sie spyder und love GUI verwenden, können Sie einfach auf die Ordnerschaltfläche in der oberen rechten Ecke Ihres Bildschirms klicken und durch die Ordner / Verzeichnisse navigieren, die Sie als aktuelles Verzeichnis wünschen. Anschließend können Sie in der Spyder-IDE zur Registerkarte "Datei-Explorer" des Fensters wechseln und alle dort vorhandenen Dateien / Ordner anzeigen. Um Ihr aktuelles Arbeitsverzeichnis zu überprüfen, gehen Sie zur Konsole von Spyder IDE und geben Sie einfach ein
Es wird derselbe Pfad gedruckt, den Sie zuvor ausgewählt haben.
quelle
Das Ändern des aktuellen Verzeichnisses des Skriptprozesses ist trivial. Ich denke, die Frage ist tatsächlich, wie man das aktuelle Verzeichnis des Befehlsfensters ändert, von dem aus ein Python-Skript aufgerufen wird, was sehr schwierig ist. Ein Bat-Skript in Windows oder ein Bash-Skript in einer Bash-Shell kann dies mit einem normalen CD-Befehl tun, da die Shell selbst der Interpreter ist. Sowohl unter Windows als auch unter Linux ist Python ein Programm, und kein Programm kann die Umgebung seiner Eltern direkt ändern. Die Kombination eines einfachen Shell-Skripts mit einem Python-Skript, das die meisten harten Aufgaben erledigt, kann jedoch das gewünschte Ergebnis erzielen. Um beispielsweise einen erweiterten CD-Befehl mit Durchlaufverlauf für Rückwärts- / Vorwärts- / Auswahl-Revisit zu erstellen, habe ich ein relativ komplexes Python-Skript geschrieben, das von einem einfachen Bat-Skript aufgerufen wird. Die Durchlaufliste wird in einer Datei gespeichert. mit dem Zielverzeichnis in der ersten Zeile. Wenn das Python-Skript zurückkehrt, liest das Bat-Skript die erste Zeile der Datei und macht es zum Argument für cd. Das vollständige Fledermaus-Skript (aus Gründen der Kürze minus Kommentare) lautet:
Das Python-Skript dSup.py lautet:
quelle