Saya ingin menjalankan skrip di dalam subdirektori / superdirectory (saya harus berada di dalam sub / super-direktori ini terlebih dahulu). Saya tidak bisa subprocess
masuk ke subdirektori saya:
tducin@localhost:~/Projekty/tests/ve$ python
Python 2.7.4 (default, Sep 26 2013, 03:20:26)
[GCC 4.7.3] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> import subprocess
>>> import os
>>> os.getcwd()
'/home/tducin/Projekty/tests/ve'
>>> subprocess.call(['cd ..'])
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/lib/python2.7/subprocess.py", line 524, in call
return Popen(*popenargs, **kwargs).wait()
File "/usr/lib/python2.7/subprocess.py", line 711, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1308, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory
Python melempar OSError dan saya tidak tahu mengapa. Tidak masalah apakah saya mencoba masuk ke subdir yang ada atau naik satu direktori (seperti di atas) - saya selalu berakhir dengan kesalahan yang sama.
python
subprocess
ducin
sumber
sumber
os.chdir()
sebagai gantinya.Jawaban:
Apa yang coba dilakukan kode Anda adalah memanggil program bernama
cd ..
. Yang Anda inginkan adalah memanggil perintah bernamacd
.Tetapi
cd
merupakan cangkang internal. Jadi Anda hanya bisa menyebutnya sebagaisubprocess.call('cd ..', shell=True) # pointless code! See text below.
Tetapi tidak ada gunanya melakukan itu. Karena tidak ada proses yang dapat mengubah direktori kerja proses lain (sekali lagi, setidaknya pada OS mirip UNIX, tetapi juga di Windows), panggilan ini akan membuat subkulit mengubah direktori dan segera keluar.
Apa yang Anda inginkan dapat dicapai dengan
os.chdir()
atau dengansubprocess
parameter bernamacwd
yang mengubah direktori kerja segera sebelum menjalankan subproses.Misalnya, untuk mengeksekusi
ls
di direktori root, Anda bisa melakukannyawd = os.getcwd() os.chdir("/") subprocess.Popen("ls") os.chdir(wd)
atau sederhananya
subprocess.Popen("ls", cwd="/")
sumber
cd
biasanya juga ada sebagai biner, tidak hanya shell bawaan. Masalah sebenarnya dari OP adalah dia memanggil binercd ..
, ya. (Dan paragraf ketiga Anda akan menjadi masalah berikutnya, jawaban yang sangat bagus.)cd
bisa bekerja sebagai biner? Itu tidak bisa chante direktori kerja orang tuanya./usr/bin/cd
terdiri daribuiltin cd "$@"
- jadi itu hanya memanggil shell built-incd
juga.cd
harus diimplementasikan sebagai perintah shell internal. Tidak ada cara lain untuk melakukannya. Perintah shell internal dijalankan dalam proses yang sama dengan shell. Yang saya maksud dengan subkulit adalah shell yang dieksekusishell=True
. Ia mendapat perintah untuk dieksekusi, mengeksekusinya dan keluar.Untuk menjalankan
your_command
sebagai subproses di direktori yang berbeda, berikancwd
parameter, seperti yang disarankan dalam jawaban @ wim :import subprocess subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)
Proses anak tidak dapat mengubah direktori kerja induknya ( biasanya ). Lari
cd ..
dalam proses cangkang anak menggunakan subproses tidak akan mengubah direktori kerja skrip Python induk Anda, misalnya, contoh kode dalam jawaban @ glglgl salah .cd
adalah shell builtin (bukan executable terpisah), itu dapat mengubah direktori hanya dalam proses yang sama .sumber
Anda ingin menggunakan jalur absolut ke file yang dapat dieksekusi, dan menggunakan
cwd
kwarg dariPopen
untuk menyetel direktori kerja. Lihat dokumennya .sumber
subprocess.call(['ls', '-l'], cwd='/')
. Ini mengubah cwd menjadi/
dan kemudian dijalankanls
dengan-l
sebagai argumen. Tetapi jika saya ingin melakukanos.chdir('/')
dan kemudianopen('etc/fstab', 'r')
, saya tidak dapat menggantios.chdir()
dengan apa punsubprocess.XXX(cwd='/')
karena tidak akan membantu, seperti yang dikatakan. Ini adalah dua skenario berbeda yang lengkap.cwd=
sesuai keinginan. Saya juga bisa melakukannyasubprocess.call(['bin/ls', '-l'], cwd='/')
.subprocess.call
dan metode lain dalamsubprocess
modul memiliki acwd
parameter.Parameter ini menentukan direktori kerja tempat Anda ingin menjalankan proses Anda.
Jadi Anda bisa melakukan sesuatu seperti ini:
subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')
Lihat docs subprocess.popen-constructor
sumber
Opsi lain berdasarkan jawaban ini: https://stackoverflow.com/a/29269316/451710
Ini memungkinkan Anda untuk menjalankan beberapa perintah (misalnya
cd
) dalam proses yang sama.import subprocess commands = ''' pwd cd some-directory pwd cd another-directory pwd ''' process = subprocess.Popen('/bin/bash', stdin=subprocess.PIPE, stdout=subprocess.PIPE) out, err = process.communicate(commands.encode('utf-8')) print(out.decode('utf-8'))
sumber
shell=True, executable='/bin/bash'
Saya kira hari ini Anda akan melakukan:
import subprocess subprocess.run(["pwd"], cwd="sub-dir")
sumber
Jika Anda ingin memiliki fungsionalitas cd (dengan asumsi shell = True) dan masih ingin mengubah direktori dengan skrip Python, kode ini akan memungkinkan perintah 'cd' untuk bekerja.
import subprocess import os def cd(cmd): #cmd is expected to be something like "cd [place]" cmd = cmd + " && pwd" # add the pwd command to run after, this will get our directory after running cd p = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE, universal_newlines=True) # run our new command out = p.stdout.read() err = p.stderr.read() # read our output if out != "": print(out) os.chdir(out[0:len(out) - 1]) # if we did get a directory, go to there while ignoring the newline if err != "": print(err) # if that directory doesn't exist, bash/sh/whatever env will complain for us, so we can just use that return
sumber
Jika Anda perlu mengubah direktori, jalankan perintah dan dapatkan juga output std:
import os import logging as log from subprocess import check_output, CalledProcessError, STDOUT log.basicConfig(level=log.DEBUG) def cmd_std_output(cd_dir_path, cmd): cmd_to_list = cmd.split(" ") try: if cd_dir_path: os.chdir(os.path.abspath(cd_dir_path)) output = check_output(cmd_to_list, stderr=STDOUT).decode() return output except CalledProcessError as e: log.error('e: {}'.format(e))
def get_last_commit_cc_cluster(): cd_dir_path = "/repos/cc_manager/cc_cluster" cmd = "git log --name-status HEAD^..HEAD --date=iso" result = cmd_std_output(cd_dir_path, cmd) return result log.debug("Output: {}".format(get_last_commit_cc_cluster()))
Output: "commit 3b3daaaaaaaa2bb0fc4f1953af149fa3921e\nAuthor: user1<[email protected]>\nDate: 2020-04-23 09:58:49 +0200\n\n
sumber
check_call
, dengan buruk.