Ada dua praktik terbaik yang harus diikuti ketika menggunakan metode ini:
Tangkap pengecualian (WindowsError, OSError) di jalur yang tidak valid. Jika pengecualian dilemparkan, jangan melakukan operasi rekursif, terutama yang merusak. Mereka akan beroperasi di jalan lama dan bukan yang baru.
Kembali ke direktori lama Anda setelah selesai. Ini dapat dilakukan dengan cara pengecualian-aman dengan membungkus panggilan chdir Anda dalam manajer konteks, seperti yang dilakukan Brian M. Hunt dalam jawabannya .
Mengubah direktori kerja saat ini dalam suatu subproses tidak mengubah direktori kerja saat ini dalam proses induk. Ini berlaku untuk juru bahasa Python juga. Anda tidak dapat menggunakan os.chdir()untuk mengubah CWD dari proses panggilan.
Jawaban berbasis dekorator ringan cdunn2001 adalah pendekatan ideal untuk Python modern. Jawaban di atas menunjukkan mengapa. Jangan pernah menelepon di os.chdir()luar manajer konteks, kecuali Anda merasa tahu apa yang Anda lakukan. ( Anda mungkin tidak. )
Cecil Curry
6
Ini adalah cara termudah dalam shell interaktif, saya pikir. Perhatikan bahwa pada Windows, Anda harus menggunakan garis miring, sepertios.chdir("C:/path/to/location")
Josiah
Satu hal yang perlu diperhatikan adalah bahwa jika Anda membuat program python Anda menjadi executable dan menjalankannya di cron, program itu akan dimulai di direktori home Anda. Jadi yang terbaik adalah menggunakan jalur yang sepenuhnya memenuhi syarat. Ini pasti berhasil, namun saya masih menggunakan jalur yang sepenuhnya memenuhi syarat dalam skrip apa pun yang saya dapat gunakan dari Python karena tidak ada jaminan bahwa ini akan berlaku di luar program Python itu sendiri.
SDsolar
310
Berikut adalah contoh manajer konteks untuk mengubah direktori kerja. Ini lebih sederhana daripada versi ActiveState dirujuk di tempat lain, tetapi ini menyelesaikan pekerjaan.
Manajer Konteks: 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.
Jika Anda perlu tahu direktori apa yang Anda ubah dari, Anda bisa menambahkannya return selfdi akhir __enter__. Dengan begitu Anda dapat melakukan with cd('foo') as cm:dan mengakses dir sebelumnya sebagaicm.savedPath
Sam F
Perhatikan bahwa ada beberapa kasus, di mana kembali ke direktori lama (yang disimpan di "SavedPath") tidak dimungkinkan. Misalnya, jika proses yang lebih diprivatisasi menjalankan proses yang kurang diprivatisasi, proses kedua mewarisi direktori kerja proses pertama, bahkan dalam kasus-kasus tersebut, di mana proses kedua tidak dapat masuk ke direktori yang berfungsi dengan kemampuannya sendiri.
Kai Petzke
140
Saya akan menggunakan os.chdirseperti ini:
os.chdir("/path/to/change/to")
Omong-omong, jika Anda perlu mencari jalan Anda saat ini, gunakan os.getcwd().
Kecemerlangan! Jika komentar pengantar dari jawaban yang diterima disuntikkan ke dalam jawaban ini, ini akan sangat ideal. Namun, jawaban singkat ini, implementasi yang aman secara Python menjamin semua upvote yang harus saya berikan.
Cecil Curry
3
Kenapa yielddan tidak return? Apakah ini seharusnya generator?
EKons
Berikan komentar tentang relevansi hasil vs pengembalian!
NicoBerrogorry
1
@NicoBerrogorry, ini generator. Lihat dokumen pada contextlib.contextmanager . Ini adalah pola yang sangat berguna dalam Python, layak dipelajari.
cdunn2001
25
Jika Anda menggunakan versi Python yang relatif baru, Anda juga dapat menggunakan manajer konteks, seperti ini :
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
MEMPERBARUI
Jika Anda lebih suka menggulung sendiri:
import os
from contextlib import contextmanager
@contextmanagerdef working_directory(directory):
owd = os.getcwd()try:
os.chdir(directory)yield directory
finally:
os.chdir(owd)
Ide umum yang bagus. Di sini resep Activestate tanpa ketergantungan lain.
cfi
4
Ketergantungan itu buruk. contextlib.contextmanagerDekorator built-in Python bagus. Lihat cdunn2001 's berbasis dekorator jawaban , yang idealnya akan menjadi jawaban yang diterima sekarang.
Cecil Curry
14
Seperti yang sudah ditunjukkan oleh orang lain, semua solusi di atas hanya mengubah direktori kerja dari proses saat ini. Ini hilang ketika Anda keluar kembali ke shell Unix. Jika putus asa Anda dapat mengubah direktori shell induk di Unix dengan hack mengerikan ini:
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")
Gila, retas rapuh mendapat upvotes wajib. Tidak seorang pun boleh melakukan ini, terutama dengan peringatan "dan jika pengguna mengetiknya saat menjalankan ..." peringatan. Tetap saja, hal itu membuat leher pemberontak tertahan dalam diriku untuk melihat bahwa mengubah CWD induk adalah semacam tapi tidak benar-benar layak. Upvotes! Upvotes untuk semua!
import os
abs_path ='C://a/b/c'
rel_path ='./folder'
os.chdir(abs_path)
os.chdir(rel_path)
Anda dapat menggunakan keduanya dengan os.chdir (abs_path) atau os.chdir (rel_path), tidak perlu memanggil os.getcwd () untuk menggunakan jalur relatif.
Jika Anda menggunakan spyder dan suka GUI, Anda cukup mengklik tombol folder di sudut kanan atas layar Anda dan menavigasi melalui folder / direktori yang Anda inginkan sebagai direktori saat ini. Setelah melakukannya, Anda dapat pergi ke tab file explorer dari jendela di spyder IDE dan Anda dapat melihat semua file / folder yang ada di sana. untuk memeriksa direktori kerja Anda saat ini, pergi ke konsol spyder IDE dan cukup ketik
pwd
itu akan mencetak jalur yang sama seperti yang Anda pilih sebelumnya.
Mengubah direktori saat ini dari proses skrip sepele. Saya pikir pertanyaan sebenarnya adalah bagaimana mengubah direktori saat ini dari jendela perintah dari mana skrip python dipanggil, yang sangat sulit. Script Bat di Windows atau skrip Bash di shell Bash dapat melakukan ini dengan perintah cd biasa karena shell itu sendiri adalah interpreter. Baik Windows dan Linux Python adalah sebuah program dan tidak ada program yang dapat secara langsung mengubah lingkungan induknya. Namun kombinasi skrip shell sederhana dengan skrip Python melakukan sebagian besar hal-hal sulit dapat mencapai hasil yang diinginkan. Sebagai contoh, untuk membuat perintah cd yang diperluas dengan riwayat traversal untuk mundur / maju / pilih kembali, saya menulis skrip Python yang relatif rumit yang dipanggil oleh skrip kelelawar sederhana. Daftar traversal disimpan dalam file, dengan direktori target di baris pertama. Ketika skrip python kembali, skrip kelelawar membaca baris pertama file dan menjadikannya argumen untuk cd. Script kelelawar lengkap (minus komentar untuk singkatnya) adalah:
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
Skrip python, dSup.py adalah:
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)
Meskipun ini adalah jawaban yang bagus, OP memilih jawaban yang mengatakan ini bukan tentang mengubah CWD dari proses induk. Itu membersihkan segala kemungkinan kebingungan tentang apa artinya pertanyaan itu.
the Tin Man
Untuk Tin Man-- jawaban itu dipilih sebelum saya mengirim saran saya. Saya pikir jawaban yang luas mungkin membingungkan. cd dalam proses yang diberikan (yaitu skrip python) sangat sederhana sehingga saya tidak tahu mengapa ada orang yang bertanya.
David McCracken
1
Sebenarnya jawaban itu dipilih bertahun-tahun yang lalu. Jika tidak tepat itu akan dipanggil berkali-kali sejak itu.
the Tin Man
Saya pikir masih ada kebingungan. Baru-baru ini, pertanyaan "mensimulasikan perintah" cd "linux dengan python, dan bertahan perubahan direktori setelah program keluar [duplikat]" ditolak karena telah dijawab di sini tetapi, pada kenyataannya, pertanyaan ini tidak diatasi oleh jawaban yang dipilih. Saran saya adalah untuk Windows tetapi masalahnya sama di Linux.
os.chdir(os.path.join(os.path.abspath(os.path.curdir),u'subfolder'))
- atau?os.getcwd()
Jawaban:
Anda dapat mengubah direktori kerja dengan:
Ada dua praktik terbaik yang harus diikuti ketika menggunakan metode ini:
Mengubah direktori kerja saat ini dalam suatu subproses tidak mengubah direktori kerja saat ini dalam proses induk. Ini berlaku untuk juru bahasa Python juga. Anda tidak dapat menggunakan
os.chdir()
untuk mengubah CWD dari proses panggilan.sumber
os.chdir()
luar manajer konteks, kecuali Anda merasa tahu apa yang Anda lakukan. ( Anda mungkin tidak. )os.chdir("C:/path/to/location")
Berikut adalah contoh manajer konteks untuk mengubah direktori kerja. Ini lebih sederhana daripada versi ActiveState dirujuk di tempat lain, tetapi ini menyelesaikan pekerjaan.
Manajer Konteks:
cd
Atau coba padanan yang lebih ringkas (di bawah) , menggunakan ContextManager .
Contoh
sumber
return self
di akhir__enter__
. Dengan begitu Anda dapat melakukanwith cd('foo') as cm:
dan mengakses dir sebelumnya sebagaicm.savedPath
Saya akan menggunakan
os.chdir
seperti ini:Omong-omong, jika Anda perlu mencari jalan Anda saat ini, gunakan
os.getcwd()
.Lebih lanjut di sini
sumber
cd()
mudah ditulis menggunakan generator dan dekorator.Lalu, direktori dikembalikan bahkan setelah sebuah pengecualian dilemparkan:
sumber
try/finally
).yield
dan tidakreturn
? Apakah ini seharusnya generator?Jika Anda menggunakan versi Python yang relatif baru, Anda juga dapat menggunakan manajer konteks, seperti ini :
MEMPERBARUI
Jika Anda lebih suka menggulung sendiri:
sumber
contextlib.contextmanager
Dekorator built-in Python bagus. Lihat cdunn2001 's berbasis dekorator jawaban , yang idealnya akan menjadi jawaban yang diterima sekarang.Seperti yang sudah ditunjukkan oleh orang lain, semua solusi di atas hanya mengubah direktori kerja dari proses saat ini. Ini hilang ketika Anda keluar kembali ke shell Unix. Jika putus asa Anda dapat mengubah direktori shell induk di Unix dengan hack mengerikan ini:
sumber
os.chdir()
adalah jalan yang benar.sumber
os.chdir()
adalah versi Pythonic daricd
.sumber
Anda dapat menggunakan keduanya dengan os.chdir (abs_path) atau os.chdir (rel_path), tidak perlu memanggil os.getcwd () untuk menggunakan jalur relatif.
sumber
Lebih jauh ke arah yang ditunjukkan oleh Brian dan berdasarkan sh (1.0.8+)
sumber
Jika Anda ingin melakukan sesuatu seperti opsi "cd ..", cukup ketik:
os.chdir ("..")
itu sama seperti di Windows cmd: cd .. Tentu saja impor os diperlukan (mis. ketik itu sebagai baris pertama dari kode Anda)
sumber
Jika Anda menggunakan spyder dan suka GUI, Anda cukup mengklik tombol folder di sudut kanan atas layar Anda dan menavigasi melalui folder / direktori yang Anda inginkan sebagai direktori saat ini. Setelah melakukannya, Anda dapat pergi ke tab file explorer dari jendela di spyder IDE dan Anda dapat melihat semua file / folder yang ada di sana. untuk memeriksa direktori kerja Anda saat ini, pergi ke konsol spyder IDE dan cukup ketik
itu akan mencetak jalur yang sama seperti yang Anda pilih sebelumnya.
sumber
Mengubah direktori saat ini dari proses skrip sepele. Saya pikir pertanyaan sebenarnya adalah bagaimana mengubah direktori saat ini dari jendela perintah dari mana skrip python dipanggil, yang sangat sulit. Script Bat di Windows atau skrip Bash di shell Bash dapat melakukan ini dengan perintah cd biasa karena shell itu sendiri adalah interpreter. Baik Windows dan Linux Python adalah sebuah program dan tidak ada program yang dapat secara langsung mengubah lingkungan induknya. Namun kombinasi skrip shell sederhana dengan skrip Python melakukan sebagian besar hal-hal sulit dapat mencapai hasil yang diinginkan. Sebagai contoh, untuk membuat perintah cd yang diperluas dengan riwayat traversal untuk mundur / maju / pilih kembali, saya menulis skrip Python yang relatif rumit yang dipanggil oleh skrip kelelawar sederhana. Daftar traversal disimpan dalam file, dengan direktori target di baris pertama. Ketika skrip python kembali, skrip kelelawar membaca baris pertama file dan menjadikannya argumen untuk cd. Script kelelawar lengkap (minus komentar untuk singkatnya) adalah:
Skrip python, dSup.py adalah:
sumber