【问题标题】:Python subprocess.popen fails when interacting with the subprocessPython subprocess.popen 与子进程交互时失败
【发布时间】:2017-07-11 11:04:54
【问题描述】:

我有一个用于 Xamarin 应用程序的 python 构建脚本,我需要根据语言环境将其编译成不同的 ipa 和 apk。

脚本处理 info.plist 和 Android 清单中的必要值,然后使用 subprocess.popen 调用 xbuild 构建每个版本。或者至少它应该是这样的。

问题是当我无论如何都与子进程交互时(基本上我需要等到它完成后才能开始更改下一个版本的值)

这行得通:

    build_path = os.path.dirname(os.path.realpath(__file__))
    ipa_path = "/path/to/my.ipa"

    cmd = '/Library/Frameworks/Mono.framework/Versions/4.6.2/Commands/xbuild /p:Configuration="Release" /p:Platform="iPhone" /p:IpaPackageDir="%s" /t:Build %s/MyApp/iOS/MyApp.iOS.csproj' % (ipa_path, build_path)

    subprocess.Popen(cmd, env=os.environ, shell=True)

但它会导致 python 脚本与构建并行继续。

如果我这样做:

    subprocess.Popen(cmd, env=os.environ, shell=True).wait()

Xbuild 失败并显示以下错误消息:

    Build FAILED.
    Errors:

    /Users/sune/dev/MyApp/iOS/MyApp.iOS.csproj: error :
    /Users/sune/dev/MyApp/iOS/MyApp.iOS.csproj: There is an unclosed literal string.
    Line 2434, position 56.

它在被调用后的几毫秒内失败,而通常构建过程需要几分钟

subprocess.popen 的任何其他简写方法,例如 .call、.check_call 以及 subprocess.poll 和 subprocess.communicate 的底层操作都会导致相同的错误发生。

真正奇怪的是,即使调用 time.sleep 也会引发同样的错误:

    subprocess.Popen(cmd, env=os.environ, shell=True)

    time.sleep(2)

我不明白,因为据我了解,我也应该能够做这样的事情:

    shell = subprocess.Popen(cmd, env=os.environ, shell=True)

    while shell.poll() is None:
        time.sleep(2)

    print "done"

基本上实现和调用 shell.wait() 一样

编辑:使用命令列表代替字符串

如果我像这样使用命令列表和 shell=False

      cmd = [
        '/Library/Frameworks/Mono.framework/Versions/4.6.2/Commands/xbuild',
        '/p:Configuration="Release"',
        '/p:Platform="iPhone"',
        '/p:IpaPackageDir="%s' % ipa_path,
        '/t:Build %s/MyApp/iOS/MyApp.iOS.csproj' % build_path

    ]

    subprocess.Popen(cmd, env=os.environ, shell=False)

那么结果是这样的:

    MSBUILD: error MSBUILD0003: Please specify the project or solution file to build, as none was found in the current directory.

非常感谢任何输入。我在这里撞墙了。

【问题讨论】:

  • 我也遇到过类似的问题。如果 xbuild 创建了一些其他进程并且它以非零状态存在,subprocess 会以某种方式捕获它并发送 SIGTERM。我最终将我的脚本移植到 bash,但我不确定在你的情况下是否可以接受
  • 如果将字符串转换为正确的参数列表并省略shell=True,会发生什么?
  • @Marat 好吧,我考虑过,但我只是觉得,我离实现我想要的很近,所以我在这里变得固执:-)
  • @RolandSmith 如果我将其更改为命令列表,无论 shell 是真还是假,我都会收到此错误:MSBUILD:错误 MSBUILD0003:请指定要构建的项目或解决方案文件,因为在当前目录。如果我用字符串更改为 shell=false,我会得到一个文件未找到错误:文件“/usr/local/Cellar/python/2.7.9/Frameworks/Python.framework/Versions/2.7/lib/python2.7/subprocess .py",第 1335 行,在 _execute_child raise child_exception OSError: [Errno 2] No such file or directory
  • @SuneKjærgård 使用带有字符串的shell=False should 失败,错误号为 2,因为没有文件名与带有所有参数的命令匹配!您可以编辑您的问题并显示您使用的 exact 命令列表吗?

标签: python xbuild


【解决方案1】:

我坚信这是不可能的。一定是子流程模块实现方式的缺点。

xbuild 在构建期间产生多个子进程,如果轮询状态,python 中的子进程将发现其中一个具有非零返回状态并停止执行一个或多个 xbuild 子进程,导致构建失败描述。

我最终使用 bash 脚本进行编译并使用 python 来操作 xml 文件等。

【讨论】:

    猜你喜欢
    • 2018-06-05
    • 2023-03-09
    • 1970-01-01
    • 1970-01-01
    • 2021-01-03
    • 2016-12-15
    • 1970-01-01
    • 2020-07-22
    • 2013-01-05
    相关资源
    最近更新 更多