Hay dos mejores prácticas a seguir cuando se utiliza este método:
Capture la excepción (WindowsError, OSError) en una ruta no válida. Si se produce la excepción, no realice ninguna operación recursiva, especialmente las destructivas. Operarán en el camino viejo y no en el nuevo.
Regrese a su antiguo directorio cuando haya terminado. Esto se puede hacer de una manera segura para excepciones envolviendo su llamada chdir en un administrador de contexto, como lo hizo Brian M. Hunt en su respuesta .
Cambiar el directorio de trabajo actual en un subproceso no cambia el directorio de trabajo actual en el proceso padre. Esto también es cierto para el intérprete de Python. No puede usar os.chdir()para cambiar la CWD del proceso de llamada.
La respuesta liviana basada en decorador de cdunn2001 es el enfoque ideal para Python moderno. La respuesta anterior demuestra por qué. Nunca llame os.chdir()fuera de un administrador de contexto, a menos que piense que sabe lo que está haciendo. ( Probablemente no. )
Cecil Curry
66
Esta es la forma más fácil en un shell interactivo, creo. Tenga en cuenta que en Windows, debe usar barras diagonales, comoos.chdir("C:/path/to/location")
Josiah, el
Lo único que debe tener en cuenta es que si convierte su programa Python en un ejecutable y lo ejecuta en cron, se iniciará en su directorio de inicio. Por lo tanto, es mejor utilizar una ruta totalmente calificada. Esto definitivamente funciona, pero todavía uso rutas totalmente calificadas en cualquier script que pueda invocar desde Python porque no hay garantía de que esto se aplique fuera del programa Python.
SDsolar
310
Aquí hay un ejemplo de un administrador de contexto para cambiar el directorio de trabajo. Es más simple que una versión ActiveState mencionada en otro lugar, pero esto hace el trabajo.
Administrador de contexto: 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)
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.
Si alguna vez necesita saber desde qué directorio cambió, puede agregar return selfal final de __enter__. De esa manera puede hacer with cd('foo') as cm:y acceder al directorio anterior comocm.savedPath
Sam F
Tenga en cuenta que hay casos en los que no es posible volver al directorio anterior (el almacenado en "savedPath"). Por ejemplo, si un proceso más privilegiado ejecuta un proceso menos privilegiado, el segundo proceso hereda el directorio de trabajo de los primeros procesos, incluso en aquellos casos en que el segundo proceso no puede ingresar a ese directorio de trabajo con sus propias capacidades.
Kai Petzke
140
Yo usaría os.chdirasí:
os.chdir("/path/to/change/to")
Por cierto, si necesita averiguar su ruta actual, use os.getcwd().
¡Brillantez! Si el comentario introductorio de la respuesta aceptada se inyectara en esta respuesta, esto sería inmensamente ideal. Aún así, la implementación concisa de Pythonically segura de esta respuesta garantiza todos los votos positivos que tengo para dar.
Cecil Curry
3
¿Por qué yieldy no return? ¿Se supone que esto es un generador?
EKons
Por favor comente sobre la relevancia de rendimiento vs retorno!
NicoBerrogorry
1
@NicoBerrogorry, es un generador. Ver documentos en contextlib.contextmanager . Este es un patrón muy útil en Python, vale la pena aprender.
cdunn2001
25
Si está usando una versión relativamente nueva de Python, también puede usar un administrador de contexto, como este :
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
ACTUALIZAR
Si prefieres rodar el tuyo:
import os
from contextlib import contextmanager
@contextmanagerdef working_directory(directory):
owd = os.getcwd()try:
os.chdir(directory)yield directory
finally:
os.chdir(owd)
Las dependencias son malas. El contextlib.contextmanagerdecorador incorporado de Python es bueno. Ver cdunn2001 's de respuesta basado en decorador , que lo ideal sería ser la respuesta aceptada ahora.
Cecil Curry
14
Como ya señalaron otros, todas las soluciones anteriores solo cambian el directorio de trabajo del proceso actual. Esto se pierde cuando vuelve a salir al shell de Unix. Si está desesperado, puede cambiar el directorio de shell principal en Unix con este horrible truco:
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")
Un hack loco y frágil recibe votos positivos obligatorios. Nadie debería hacer esto, particularmente con esa advertencia "y si el usuario escribe mientras se ejecuta ...". Aún así, me excita la barba rebelde en mí al ver que cambiar el CWD padre es algo así como realmente no factible. ¡Votos a favor! ¡Votos a favor para todos!
Si desea realizar algo como la opción "cd ..", simplemente escriba:
os.chdir ("..")
es lo mismo que en Windows cmd: cd .. Por supuesto, la importación del sistema operativo es necesaria (por ejemplo, escríbala como primera línea de su código)
Si usa Spyder and Love GUI, simplemente puede hacer clic en el botón de carpeta en la esquina superior derecha de su pantalla y navegar a través de las carpetas / directorios que desee como directorio actual. Después de hacerlo, puede ir a la pestaña del explorador de archivos de la ventana en Spyder IDE y puede ver todos los archivos / carpetas presentes allí. para verificar su directorio de trabajo actual, vaya a la consola del IDE spyder y simplemente escriba
pwd
imprimirá la misma ruta que ha seleccionado anteriormente.
Cambiar el directorio actual del proceso de script es trivial. Creo que la pregunta es cómo cambiar el directorio actual de la ventana de comandos desde el que se invoca un script de Python, lo cual es muy difícil. Un script Bat en Windows o un script Bash en un shell Bash puede hacer esto con un comando de CD ordinario porque el shell en sí es el intérprete. Tanto en Windows como en Linux, Python es un programa y ningún programa puede cambiar directamente el entorno de su padre. Sin embargo, la combinación de un script de shell simple con un script de Python que hace la mayoría de las cosas difíciles puede lograr el resultado deseado. Por ejemplo, para hacer un comando de CD extendido con historial de recorrido para volver a visitar hacia atrás / adelante / seleccionar, escribí un script de Python relativamente complejo invocado por un simple script de murciélago. La lista transversal se almacena en un archivo, con el directorio de destino en la primera línea. Cuando regresa el script python, el script bat lee la primera línea del archivo y lo convierte en el argumento de cd. El guión completo de murciélagos (menos comentarios por brevedad) es:
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
El script de Python, dSup.py es:
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)
Si bien es una buena respuesta, el OP seleccionó una respuesta que dice que no se trata de cambiar el CWD del proceso principal. Eso aclara cualquier posible confusión sobre lo que significa la pregunta.
The Tin Man
Para Tin Man, esa respuesta fue seleccionada antes de publicar mi sugerencia. Creo que las amplias respuestas pueden haber sido confusas. cd dentro de un proceso dado (es decir, un script de python) es tan simple que no sé por qué alguien lo preguntaría.
David McCracken
1
En realidad, esa respuesta fue seleccionada hace años . Si no fuera apropiado, habría sido llamado muchas veces desde entonces.
The Tin Man
Creo que la confusión persiste. Más recientemente, la pregunta "simulando el comando" cd "de linux en python, y persiste el cambio de directorio después de que el programa sale [duplicado]" se descartó como respondida aquí, pero, de hecho, esta pregunta no se aborda en la respuesta seleccionada. Mi sugerencia es para Windows pero los problemas son los mismos en Linux.
os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subfolder'))
, ¿o?os.getcwd()
Respuestas:
Puede cambiar el directorio de trabajo con:
Hay dos mejores prácticas a seguir cuando se utiliza este método:
Cambiar el directorio de trabajo actual en un subproceso no cambia el directorio de trabajo actual en el proceso padre. Esto también es cierto para el intérprete de Python. No puede usar
os.chdir()
para cambiar la CWD del proceso de llamada.fuente
os.chdir()
fuera de un administrador de contexto, a menos que piense que sabe lo que está haciendo. ( Probablemente no. )os.chdir("C:/path/to/location")
Aquí hay un ejemplo de un administrador de contexto para cambiar el directorio de trabajo. Es más simple que una versión ActiveState mencionada en otro lugar, pero esto hace el trabajo.
Administrador de contexto:
cd
O pruebe el equivalente más conciso (a continuación) , utilizando ContextManager .
Ejemplo
fuente
return self
al final de__enter__
. De esa manera puede hacerwith cd('foo') as cm:
y acceder al directorio anterior comocm.savedPath
Yo usaría
os.chdir
así:Por cierto, si necesita averiguar su ruta actual, use
os.getcwd()
.Más aquí
fuente
cd()
Es fácil de escribir usando un generador y un decorador.Luego, el directorio se revierte incluso después de que se lanza una excepción:
fuente
try/finally
).yield
y noreturn
? ¿Se supone que esto es un generador?Si está usando una versión relativamente nueva de Python, también puede usar un administrador de contexto, como este :
ACTUALIZAR
Si prefieres rodar el tuyo:
fuente
contextlib.contextmanager
decorador incorporado de Python es bueno. Ver cdunn2001 's de respuesta basado en decorador , que lo ideal sería ser la respuesta aceptada ahora.Como ya señalaron otros, todas las soluciones anteriores solo cambian el directorio de trabajo del proceso actual. Esto se pierde cuando vuelve a salir al shell de Unix. Si está desesperado, puede cambiar el directorio de shell principal en Unix con este horrible truco:
fuente
os.chdir()
Es el camino correcto.fuente
os.chdir()
es la versión pitónica decd
.fuente
Puede usar ambos con os.chdir (abs_path) o os.chdir (rel_path), no es necesario llamar a os.getcwd () para usar una ruta relativa.
fuente
Más en la dirección señalada por Brian y basada en sh (1.0.8+)
fuente
Si desea realizar algo como la opción "cd ..", simplemente escriba:
os.chdir ("..")
es lo mismo que en Windows cmd: cd .. Por supuesto, la importación del sistema operativo es necesaria (por ejemplo, escríbala como primera línea de su código)
fuente
Si usa Spyder and Love GUI, simplemente puede hacer clic en el botón de carpeta en la esquina superior derecha de su pantalla y navegar a través de las carpetas / directorios que desee como directorio actual. Después de hacerlo, puede ir a la pestaña del explorador de archivos de la ventana en Spyder IDE y puede ver todos los archivos / carpetas presentes allí. para verificar su directorio de trabajo actual, vaya a la consola del IDE spyder y simplemente escriba
imprimirá la misma ruta que ha seleccionado anteriormente.
fuente
Cambiar el directorio actual del proceso de script es trivial. Creo que la pregunta es cómo cambiar el directorio actual de la ventana de comandos desde el que se invoca un script de Python, lo cual es muy difícil. Un script Bat en Windows o un script Bash en un shell Bash puede hacer esto con un comando de CD ordinario porque el shell en sí es el intérprete. Tanto en Windows como en Linux, Python es un programa y ningún programa puede cambiar directamente el entorno de su padre. Sin embargo, la combinación de un script de shell simple con un script de Python que hace la mayoría de las cosas difíciles puede lograr el resultado deseado. Por ejemplo, para hacer un comando de CD extendido con historial de recorrido para volver a visitar hacia atrás / adelante / seleccionar, escribí un script de Python relativamente complejo invocado por un simple script de murciélago. La lista transversal se almacena en un archivo, con el directorio de destino en la primera línea. Cuando regresa el script python, el script bat lee la primera línea del archivo y lo convierte en el argumento de cd. El guión completo de murciélagos (menos comentarios por brevedad) es:
El script de Python, dSup.py es:
fuente