Python subprocess.popen 与子进程交互时失败
Python subprocess.popen fails when interacting with the subprocess
我有一个 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 的任何其他 shorthand 方法,例如 .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.
非常感谢任何意见。我在这里用头撞墙。
我坚信这是不可能的。肯定是subprocess模块实现方式的不足
xbuild 在构建期间生成多个子进程,如果轮询状态 python 中的子进程将发现其中一个具有非零 return 状态并停止执行一个或多个导致构建失败的 xbuild 子进程的数量,如所述。
我最终使用 bash 脚本进行编译并使用 python 操作 xml 文件等
我有一个 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 的任何其他 shorthand 方法,例如 .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.
非常感谢任何意见。我在这里用头撞墙。
我坚信这是不可能的。肯定是subprocess模块实现方式的不足
xbuild 在构建期间生成多个子进程,如果轮询状态 python 中的子进程将发现其中一个具有非零 return 状态并停止执行一个或多个导致构建失败的 xbuild 子进程的数量,如所述。
我最终使用 bash 脚本进行编译并使用 python 操作 xml 文件等