Chcę wykonać skrypt w podkatalogu / superkatalogu (najpierw muszę być w tym podkatalogu / superkatalogu). Nie mogę wejść subprocess
do mojego podkatalogu:
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 wyrzuca OSError i nie wiem dlaczego. Nie ma znaczenia, czy próbuję wejść do istniejącego podkatalogu, czy przejść o jeden katalog wyżej (jak wyżej) - zawsze kończy się ten sam błąd.
python
subprocess
ducin
źródło
źródło
os.chdir()
zamiast tego użyjesz .Odpowiedzi:
To, co próbuje zrobić twój kod, to wywołać program o nazwie
cd ..
. To, czego chcesz, to wywołanie polecenia o nazwiecd
.Ale
cd
jest skorupa wewnętrzna. Możesz więc nazwać to tylko jakosubprocess.call('cd ..', shell=True) # pointless code! See text below.
Ale to nie ma sensu. Ponieważ żaden proces nie może zmienić katalogu roboczego innego procesu (ponownie, przynajmniej w systemie podobnym do systemu UNIX, ale także w systemie Windows), to wywołanie spowoduje, że podpowłoka zmieni swój katalog i natychmiast zakończy pracę.
To, co chcesz, można osiągnąć za
os.chdir()
pomocąsubprocess
nazwanego parametru,cwd
który zmienia katalog roboczy bezpośrednio przed wykonaniem podprocesu.Na przykład, aby wykonać
ls
w katalogu głównym, możesz to zrobićwd = os.getcwd() os.chdir("/") subprocess.Popen("ls") os.chdir(wd)
lub po prostu
subprocess.Popen("ls", cwd="/")
źródło
cd
zwykle istnieje również jako plik binarny, a nie tylko jako wbudowana powłoka. Prawdziwym problemem OP było to, że dzwonił do binarnegocd ..
, tak. (A twój trzeci akapit byłby jego następnym problemem, więc dobra odpowiedź.)cd
działać jako plik binarny? Nie może śpiewać pracy rodzica w reż./usr/bin/cd
składa się zbuiltin cd "$@"
- więc po prostu wywołuje również wbudowaną powłokęcd
.cd
musi być zaimplementowane jako wewnętrzne polecenie powłoki. Nie ma innego sposobu, aby to zrobić. Polecenia powłoki wewnętrznej są wykonywane w ramach tego samego procesu co powłoka. Przez podpowłokę rozumiałem powłokę, dla której wykonuje sięshell=True
. Pobiera polecenie do wykonania, wykonuje je i wychodzi.Aby uruchomić
your_command
jako podproces w innym katalogu, przekażcwd
parametr, zgodnie z sugestią w odpowiedzi @ wim :import subprocess subprocess.check_call(['your_command', 'arg 1', 'arg 2'], cwd=working_dir)
Proces potomny nie może ( normalnie ) zmienić katalogu roboczego swojego rodzica . Uruchomienie
cd ..
w procesie powłoki potomnej przy użyciu podprocesu nie zmieni katalogu roboczego twojego nadrzędnego skryptu Python, tj. Przykładowy kod w odpowiedzi @ glglgl jest nieprawidłowy .cd
jest wbudowaną powłoką (nie jest oddzielnym plikiem wykonywalnym), może zmienić katalog tylko w tym samym procesie.źródło
Chcesz użyć bezwzględnej ścieżki do pliku wykonywalnego i użyć
cwd
kwarg of,Popen
aby ustawić katalog roboczy. Zobacz dokumentację .źródło
subprocess.call(['ls', '-l'], cwd='/')
. To zmienia cwd na,/
a następnie uruchamia sięls
z-l
argumentem. Ale jeśli chcę zrobićos.chdir('/')
, a następnieopen('etc/fstab', 'r')
, nie mogę wymienićos.chdir()
z niczego na tematsubprocess.XXX(cwd='/')
, jak to nie pomoże, jak powiedział. To są dwa zupełnie różne scenariusze.cwd=
zgodnie z przeznaczeniem. Równie dobrze mogęsubprocess.call(['bin/ls', '-l'], cwd='/')
.subprocess.call
a inne metody wsubprocess
module mającwd
parametr.Ten parametr określa katalog roboczy, w którym chcesz wykonać proces.
Możesz więc zrobić coś takiego:
subprocess.call('ls', shell=True, cwd='path/to/wanted/dir/')
Sprawdź konstruktor subprocess.popen dokumentów
źródło
Inna opcja oparta na tej odpowiedzi: https://stackoverflow.com/a/29269316/451710
Pozwala to na wykonywanie wielu poleceń (np.
cd
) W tym samym procesie.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'))
źródło
shell=True, executable='/bin/bash'
Myślę, że w tych dniach zrobiłbyś:
import subprocess subprocess.run(["pwd"], cwd="sub-dir")
źródło
Jeśli chcesz mieć funkcjonalność cd (zakładając, że shell = True) i nadal chcesz zmienić katalog pod względem skryptu Python, ten kod pozwoli na działanie poleceń „cd”.
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
źródło
po prostu użyj
os.chdir
przykładu:
>>> import os >>> import subprocess >>> # Lets Just Say WE want To List The User Folders >>> os.chdir("/home/") >>> subprocess.run("ls") user1 user2 user3 user4
źródło
Jeśli chcesz zmienić katalog, uruchom polecenie i uzyskaj również standardowe wyjście:
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
źródło
check_call
Słabo wymyślasz na nowo .