【问题标题】:Why calling Python script from setup.py invokes Python shell instead?为什么从 setup.py 调用 Python 脚本会调用 Python shell?
【发布时间】:2013-10-30 19:08:41
【问题描述】:

我尝试在安装期间使用自定义安装从 setup.py 调用 Python 脚本:

class CustomInstall(install):
    def run(self):
        install.run(self)

        ...

        p = subprocess.Popen(
            [sys.executable, 'demo_package/deploy_database.py'],
            shell=True,
            stdout=subprocess.PIPE,
            cwd=os.path.join(self.install_lib, 'demo_package'))

        out, err = p.communicate()

setup(..., cmdclass=dict(install=CustomInstall))

在 Ubuntu 机器上部署包时,该进程不会执行 deploy_database.py,而是显示任何内容。当我使用 Ctrl+C 手动停止它时,输出似乎表明它没有实际运行 deploy_database.py,而是简单地启动了 Python:

^CDownloading/unpacking PypiPackagesMonitoring
  Downloading demo-1.0.64.zip  
  Running setup.py egg_info for package demo

Installing collected packages: demo
  Running setup.py install for demo

    Python 3.3.2+ (default, Oct  9 2013, 14:50:09)
    [GCC 4.8.1 on linux
    Type "help", "copyright", "credits" or "license" for more information.
Cleaning up...
Operation cancelled by the user
Storing complete log in /home/.../.pip/pip.log

我调用 Python 脚本的方式有什么问题?我应该怎么做呢?

【问题讨论】:

  • 或者你可以使用execfile。
  • shell=True 应该暗示您需要一个不能表示为简单字符串序列的功能,即当使用shell=True 时,您必须使用一个字符串来表示整个shell 命令*(它*不是简单地调用外部程序,而是包括一些shell 功能,例如管道/重定向/调用内置等)。否则,您应该使用shell=False,您可以用sys.argv 的相同格式表示要执行的程序及其参数。混合这两种方法会导致这种奇怪的结果。

标签: python subprocess pip easy-install


【解决方案1】:

shell=True 不需要 [sys.executable, 'demo_package/deploy_database.py'],会导致问题。你这样做的方式(如果你省略shell=True)是首选方式,因为它绕过了shell。

shell=True 使 Popen 将传递的命令交给 shell(例如 /bin/bash,取决于为当前用户配置的 shell)。仅执行列表中传递的第一个命令,列表的其他元素作为参数传递给 shell 本身(来自docs):

在 Unix 上 shell=True […] 如果 args 是一个序列,第一项指定命令字符串,任何附加项都将被视为 shell 本身的附加参数。

shell=True 有点危险,但在某些情况下也很有用。详情请见the documentation。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2018-03-25
    • 2012-01-23
    • 2019-10-31
    • 2013-07-27
    • 2017-04-23
    • 1970-01-01
    • 2011-04-16
    • 2016-03-13
    相关资源
    最近更新 更多