web-dev-qa-db-ja.com

subprocess.Popenの単純なコードでは、cd(ディレクトリの変更)を実行できません

Pythonスクリプトを使用してディレクトリを変更しようとしていますが、エラーが発生します。

pythonコード:

import subprocess
p = subprocess.Popen(['cd', '~'], stdout=subprocess.PIPE)
output = p.communicate()
print output

このエラーが発生します:

File "test_sub.py", line 2, in <module>
p = subprocess.Popen(['cd', '~'], stdout=subprocess.PIPE)
File "/usr/lib/python2.7/subprocess.py", line 710, in __init__
errread, errwrite)
File "/usr/lib/python2.7/subprocess.py", line 1327, in _execute_child
raise child_exception
OSError: [Errno 2] No such file or directory

エラーの意味、間違っていること、pythonサブプロセスのディレクトリを変更するにはどうすればよいですか?

9
user3512904
_>>> Popen('cd ~', Shell=True, stdout=PIPE).communicate()
(b'', None)
_

_Shell=True_なし(これはシェルをエミュレートします)

_>>> Popen(['cd', '~'], stdout=PIPE).communicate()
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.4/subprocess.py", line 858, in __init__
    restore_signals, start_new_session)
  File "/usr/lib/python3.4/subprocess.py", line 1456, in _execute_child
    raise child_exception_type(errno_num, err_msg)
FileNotFoundError: [Errno 2] No such file or directory: 'cd'
>>> 
_

次の方法で行わない限り、ディレクトリを変更することはできません。

_import os
os.chdir(os.path.abspath(os.path.expanduser('~')))
_

したがって、問題はパス_~_が存在しないことではなく、Pythonのエミュレートされた端末にオプションとしてcdが存在しないことです。実際のシェルに直接渡すと、cdが機能します。ただし、_Shell=True_はリスクであることに注意してください。必要がない限り、絶対に使用しないでください。
したがって、代わりに_os.chdir_を使用してください。

作業シナリオ:

_import os, subprocess
os.chdir(os.path.abspath('/tmp/'))
print(subprocess.Popen(['ls', '-lah'], stdout=subprocess.PIPE).communicate()[0].decode('utf-8'))
_

その結果:

_[torxed@archie ~]$ python
Python 3.4.1 (default, May 19 2014, 17:23:49) 

>>> import os, subprocess
>>> os.chdir(os.path.abspath('/tmp/'))
>>> print(subprocess.Popen(['ls', '-lah'], stdout=subprocess.PIPE).communicate()[0].decode('utf-8'))

total 12K
drwxrwxrwt  9 root   root   220 Jun 11 12:08 .
drwxr-xr-x 19 root   root  4.0K May 28 08:03 ..
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .font-unix
drwx------  2 torxed users   60 Jun 11 09:33 gpg-LBLcdd
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .ICE-unix
drwx------  2 torxed users   80 Jun 11 09:34 .org.chromium.Chromium.LEqfXB
-rw-------  1 torxed users  153 Jun 11 09:34 serverauth.EHWB0LqCv6
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .Test-unix
-r--r--r--  1 root   users   11 Jun 11 09:34 .X0-lock
drwxrwxrwt  2 root   root    60 Jun 11 09:34 .X11-unix
drwxrwxrwt  2 root   root    40 Jun 11 09:30 .XIM-unix

>>> 
_

シェルを_~_で開始し、_os.chdir_を介してそれをtmpに変更し、実際にtmpディレクトリのコンテンツを取得したことに注意してください。

シェルとコマンドの説明:

シェルコマンドはシェルに組み込まれているものですが、通常の古いコマンドは_/bin_の下にあります。例:

_[torxed@archie ~]$ ls /bin
2to3            2to3-2.7
7z              7za
...
_

7zは、実際に実行できるコマンドです。

_>>> from subprocess import *
>>> Popen(['7z'], stdout=PIPE).communicate()

(b'\n7-Zip [64] 9.20  Copyright (c) 1999-2010 Igor Pavlov  2010-11-18\np7Zip Version 9.20 (locale=en_US.UTF-8,Utf16=on,HugeFiles=on,8 CPUs)\n
_

たとえば、cdは組み込みのシェルコマンドですが、_/bin_の下にはありませんが、(前述のように)組み込みであるため、ほとんどの「端末」(シェルを使用)で機能します。あなたが通常見るシェル。

しかし、Pythonはシェルをエミュレートする組み込みで機能するコマンドの特定のセットしかないため、cd補償する以外にないものの1つであるため、os.chdir(...)を使用してまったく同じ関数を実行し、プログラム全体に影響を与えることができます。

9
Torxed

cdはシェルの組み込みコマンドであり、シェルの環境を変更して、次に実行されるコマンドの現在のディレクトリを設定します。 not通常のプログラムです。したがって、Popenのサブプロセスとして呼び出すことはできません。

python内の現在のディレクトリを変更する正しい方法は次のとおりです。

import os
os.chdir(os.path.abspath(os.path.expanduser('~')))
#now the current directory is home of user
1
Xavier Combelle

すべてのパスを含める必要があります

path = os.path.dirname('$0')
currentpath = os.path.abspath(path)
os.chdir(path)
0
Isabel Cenamor