【发布时间】: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=Falseshould 失败,错误号为 2,因为没有文件名与带有所有参数的命令匹配!您可以编辑您的问题并显示您使用的 exact 命令列表吗?