subprocess.Popen simple code does not allow me to perform a cd (change directory)

前端 未结 3 927
温柔的废话
温柔的废话 2020-12-06 12:24

I\'m trying to use a Python script to change directory, but I am getting an error.

The python code:

import subprocess
p = subprocess.Popen([\'cd\',         


        
3条回答
  •  再見小時候
    2020-12-06 12:25

    >>> Popen('cd ~', shell=True, stdout=PIPE).communicate()
    (b'', None)
    

    Without shell=True (which, emulates a shell)

    >>> Popen(['cd', '~'], stdout=PIPE).communicate()
    Traceback (most recent call last):
      File "", line 1, in 
      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'
    >>> 
    

    You can't change directory unless you do it via:

    import os
    os.chdir(os.path.abspath(os.path.expanduser('~')))
    

    So the problem isn't that the path ~ doesn't exist, but rather cd doesn't exist as an option in the emulated terminal of Python. Passing directly to an actual shell makes cd work. But note that shell=True is a risk, never use it unless you need to..
    So use os.chdir instead.

    A working scenario:

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

    Resulting in:

    [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
    
    >>> 
    

    Note that i started the shell in ~ and via os.chdir changed it to tmp and actually got my tmp directory content.

    Explanation of shells and commands:

    A shell-command is something that's built into the shell while a regular old command is something you'll find under /bin, for instance:

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

    Where 7z is a command i can actually execute:

    >>> 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
    

    While for instance cd is a built in shell command, something that you will not find under /bin but works anyway in most "terminals" (using a shell) because it's (as mentioned), built into the shell you normally see.

    But because Python will emulate a shell there are only a certain set of commands that are built-in and works, cd being one of those that doesn't but to compensate you can use os.chdir(...) to execute the exact same function and affects the entire program.

提交回复
热议问题