Python subprocess.popen завершается ошибкой при взаимодействии с подпроцессом
У меня есть скрипт сборки Python для приложения Xamarin, который мне нужно скомпилировать в разные 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.
Любой вклад очень ценится. Я бьюсь головой о стену здесь.
1 ответ
Я твердо верю, что это невозможно. Это должно быть недостатком способа реализации модуля подпроцесса.
xbuild порождает несколько подпроцессов во время сборки, и при опросе на состояние подпроцесс в python обнаружит, что один из них имеет ненулевой статус возврата, и остановит выполнение одного или нескольких подпроцессов xbuild, что приведет к сбою сборки, как описано.
В итоге я использовал скрипт bash для компиляции и использовал python для работы с XML-файлами и т. Д.