Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/bash/17.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/flash/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python子流程。检查_call()不识别pushd和popd_Python_Bash_Python 3.x_Subprocess_Ubuntu 15.04 - Fatal编程技术网

Python子流程。检查_call()不识别pushd和popd

Python子流程。检查_call()不识别pushd和popd,python,bash,python-3.x,subprocess,ubuntu-15.04,Python,Bash,Python 3.x,Subprocess,Ubuntu 15.04,我使用的是Ubuntu 15.04(显然不是随意选择的)和Python3.4.3,我正在尝试执行以下内容 subprocess.check_call("pushd /tmp", shell=True) 我需要shell=True,因为我试图执行的实际代码包含需要解释的通配符。但是,这给了我以下错误 /usr/lib/python3.4/subprocess.py in check_call(*popenargs, **kwargs) 559 if cmd is None

我使用的是Ubuntu 15.04(显然不是随意选择的)和Python3.4.3,我正在尝试执行以下内容

subprocess.check_call("pushd /tmp", shell=True)
我需要
shell=True
,因为我试图执行的实际代码包含需要解释的通配符。但是,这给了我以下错误

/usr/lib/python3.4/subprocess.py in check_call(*popenargs, **kwargs)
    559         if cmd is None:
    560             cmd = popenargs[0]
--> 561         raise CalledProcessError(retcode, cmd)
    562     return 0
    563 

CalledProcessError: Command 'pushd /tmp' returned non-zero exit status 127

我在我的Mac电脑(El Capitan和Python 3.5.1)上也做过同样的事情,效果非常好。我还尝试过在Ubuntu15.04和Python3.4.3上执行
subprocess.check_调用(“ls”,shell=True)
(用于健全性检查),效果很好。作为最后一次检查,我在Ubuntu 15.04的Bash中尝试了命令
pushd/tmp&&popd
,效果也不错。因此,不知何故,在(我的)使用Python 3.4.3的Ubuntu15.04上,
子进程。check_call()
无法识别
pushd
popd
!为什么?

您的代码有两个问题。第一个是默认使用的shell是
/bin/sh
,它不支持
pushd
popd
。 在您的问题中,您没有提供完整的错误输出,在问题的顶部,您应该看到一行:

/bin/sh: 1: popd: not found
下次请记住发布整个错误消息,而不仅仅是您(错误地)认为相关的部分

您可以通过
可执行文件
参数告诉
子流程
模块要使用哪个shell来解决此问题:

>>> subprocess.check_call('pushd ~', shell=True, executable='/bin/bash')
~ ~
0
第二个问题是,即使这样,如果使用多个
check\u调用
调用,也会出现错误:

>>> subprocess.check_call('pushd ~', shell=True, executable='/bin/bash')
~ ~
0
>>> subprocess.check_call('popd', shell=True, executable='/bin/bash')
/bin/bash: riga 0: popd: stack delle directory vuoto
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'popd' returned non-zero exit status 1
现在的事实是,如果您想从python中以这种方式使用
pushd
popd
。。。它们是无用的。这是因为您可以通过
cwd
参数指定当前工作目录,因此您可以从python跟踪工作目录堆栈,而无需依赖
pushd
popd

current_working_dirs = []

def pushd(dir):
    current_working_dirs.append(os.path.realpath(os.path.expanduser(dir)))

def popd():
    current_working_dirs.pop()


def run_command(cmdline, **kwargs):
    return subprocess.check_call(cmdline, cwd=current_working_dirs[-1], **kwargs)
检查调用('pushd xxx')
替换为
pushd('xxx')
,将
检查调用('popd')
替换为
popd
,并使用
运行命令(…)
代替
检查调用(…)


正如您所建议的,更优雅的解决方案是使用上下文管理器:

class Pwd:
    dir_stack = []

    def __init__(self, dirname):
        self.dirname = os.path.realpath(os.path.expanduser(self.dirname))

    def __enter__(self):
        Pwd.dir_stack.append(self.dirname)
        return self

    def __exit__(self,  type, value, traceback):
        Pwd.dir_stack.pop()

    def run(self, cmdline, **kwargs):
        return subprocess.check_call(cmdline, cwd=Pwd.dir_stack[-1], **kwargs)
用作:

with Pwd('~') as shell:
    shell.run(command)
    with Pwd('/other/directory') as shell:
        shell.run(command2)   # runs in '/other/directory'
    shell.run(command3)       # runs in '~'

您的代码有两个问题。第一个是默认使用的shell是
/bin/sh
,它不支持
pushd
popd
。 在您的问题中,您没有提供完整的错误输出,在问题的顶部,您应该看到一行:

/bin/sh: 1: popd: not found
下次请记住发布整个错误消息,而不仅仅是您(错误地)认为相关的部分

您可以通过
可执行文件
参数告诉
子流程
模块要使用哪个shell来解决此问题:

>>> subprocess.check_call('pushd ~', shell=True, executable='/bin/bash')
~ ~
0
第二个问题是,即使这样,如果使用多个
check\u调用
调用,也会出现错误:

>>> subprocess.check_call('pushd ~', shell=True, executable='/bin/bash')
~ ~
0
>>> subprocess.check_call('popd', shell=True, executable='/bin/bash')
/bin/bash: riga 0: popd: stack delle directory vuoto
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "/usr/lib/python3.5/subprocess.py", line 581, in check_call
    raise CalledProcessError(retcode, cmd)
subprocess.CalledProcessError: Command 'popd' returned non-zero exit status 1
现在的事实是,如果您想从python中以这种方式使用
pushd
popd
。。。它们是无用的。这是因为您可以通过
cwd
参数指定当前工作目录,因此您可以从python跟踪工作目录堆栈,而无需依赖
pushd
popd

current_working_dirs = []

def pushd(dir):
    current_working_dirs.append(os.path.realpath(os.path.expanduser(dir)))

def popd():
    current_working_dirs.pop()


def run_command(cmdline, **kwargs):
    return subprocess.check_call(cmdline, cwd=current_working_dirs[-1], **kwargs)
检查调用('pushd xxx')
替换为
pushd('xxx')
,将
检查调用('popd')
替换为
popd
,并使用
运行命令(…)
代替
检查调用(…)


正如您所建议的,更优雅的解决方案是使用上下文管理器:

class Pwd:
    dir_stack = []

    def __init__(self, dirname):
        self.dirname = os.path.realpath(os.path.expanduser(self.dirname))

    def __enter__(self):
        Pwd.dir_stack.append(self.dirname)
        return self

    def __exit__(self,  type, value, traceback):
        Pwd.dir_stack.pop()

    def run(self, cmdline, **kwargs):
        return subprocess.check_call(cmdline, cwd=Pwd.dir_stack[-1], **kwargs)
用作:

with Pwd('~') as shell:
    shell.run(command)
    with Pwd('/other/directory') as shell:
        shell.run(command2)   # runs in '/other/directory'
    shell.run(command3)       # runs in '~'

我现在编辑了我的问题。对不起,我早早犯了一个错误。我知道
check\u call()
会产生一个新的shell。问题不在于调用
pushd
后调用
popd
;实际上,pushd本身就是如此。@Ray根据您的更新,Bakuriu回答的关键部分是shell不是bash,因此没有可用的pushd。在Ubuntu上试着启动sh并做一个pushd。@Ray我已经重新组织了我的答案,以便更清楚。另外:如果用python编写,IMHO pushd和popd是无用的,只需使用字符串列表作为堆栈,并将正确的
cwd=
参数传递给子进程调用。谢谢@Bakuriu。我没有提供完整的错误输出,因为我在Jupyter笔记本中运行它,它没有像普通Python shell那样输出那么多错误消息。如果我使用了普通的Python shell,我可能会注意到它。@Bakuriu我也同意你的观点,即
pushd
popd
应该被更具Python风格的东西所取代,我想实现一个名为
pushd
的上下文类,其中包含
\uuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuuu和,以便使用with语句。但是我写了一些快速而肮脏的管理内容,需要大量的Python,这个问题引起了我的好奇心。我现在编辑了我的问题。对不起,我早早犯了一个错误。我知道
check\u call()
会产生一个新的shell。问题不在于调用
pushd
后调用
popd
;实际上,pushd本身就是如此。@Ray根据您的更新,Bakuriu回答的关键部分是shell不是bash,因此没有可用的pushd。在Ubuntu上试着启动sh并做一个pushd。@Ray我已经重新组织了我的答案,以便更清楚。另外:如果用python编写,IMHO pushd和popd是无用的,只需使用字符串列表作为堆栈,并将正确的
cwd=
参数传递给子进程调用。谢谢@Bakuriu。我没有提供完整的错误输出,因为我在Jupyter笔记本中运行它,它没有像普通Python shell那样输出那么多错误消息。如果我使用了普通的Python shell,我可能会注意到它。@Bakuriu我也同意你的观点,即
pushd
popd
应该被更具Python风格的东西所取代,我正在考虑一个名为
pushd
的上下文类