Python подождите, пока не закончится os.system

Мне нужно запустить внешний скрипт (это невозможно изменить), чтобы управлять данными CLOB и вставлять их в таблицу. Но если я использую os.system в цикле, в таблицу вставляется только 1 запись, если я добавляю time.sleep(20) между вызовами, все работает нормально.

Я пытаюсь использовать подпроцесс, но инструкция очень большая и команда возвращает Errno 36 filename too long.

В этом случае была вставлена ​​только последняя запись:

for element in list:
   query = 'INSERT IN TABLE1 VALUES(<clob>)'
   rc = os.system('externalScript.py -q "' + query.encode('utf-8') + '"')

В этом случае подпроцесс возвращает filename too long:

for element in list:
   query = 'INSERT IN TABLE1 VALUES(<clob>)'
   proc = subprocess.Popen(['python', 'externalScript.py -q "' +  query.encode('utf-8') + '"' ], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Есть ли решение без добавления time.sleep(20) после os.system?


person SirLancillotto    schedule 04.03.2021    source источник
comment
Сможете ли вы import externalScript использовать его без вызова подпроцесса?   -  person ex4    schedule 04.03.2021
comment
os.system() по определению уже ждет завершения внешнего процесса.   -  person tripleee    schedule 04.03.2021
comment
Правильный синтаксис будет subprocess.Popen(['python', 'externalScript.py', '-q', query], text=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT), но на самом деле не используйте здесь Popen(); переключиться на subprocess.check_call или, возможно, subprocess.call или subprocess.run(..., check=True) ... за исключением, конечно, запуска Python в качестве подпроцесса, как правило, также неправильно. Просто import externalScript (возможно, вам нужно будет его отрефакторить) и вызовите его основную функцию прямо из текущего скрипта.   -  person tripleee    schedule 04.03.2021
comment
Та же проблема с subprocess.call: [Errno 36] Слишком длинное имя файла.   -  person SirLancillotto    schedule 04.03.2021
comment
Я не могу импортировать externalScript, это скрипт 3PP, и я могу использовать только вызов   -  person SirLancillotto    schedule 04.03.2021
comment
Просто переключиться на subprocess.call не получится, потому что у вас все еще есть синтаксическая ошибка, которую необходимо исправить. Если ваш аргумент достаточно длинный, чтобы вызвать это предупреждение, вероятно, было бы лучше, если бы вы могли заставить скрипт читать файл или стандартный ввод.   -  person tripleee    schedule 04.03.2021


Ответы (2)


Для вашего вызова subprocess.Popen (который, как отмечали другие, должен быть subprocess.call), вы должны передавать имя скрипта и аргументы отдельно и без других кавычек, например:

for element in list:
   query='INSERT IN TABLE1 VALUES(<clob>)'
   proc = subprocess.call(['python', 'externalScript.py', '-q',  query.encode('utf-8')], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)

Однако это, вероятно, не будет улучшением по сравнению с os.system; оба должны дождаться завершения внешнего сценария. Что-то не так либо в этом внешнем скрипте, либо в какой-либо базе данных, к которой он подключается, и его нельзя вызвать в быстрой последовательности.

person sabik    schedule 04.03.2021

subprocess.Popen — неблокирующий вызов. Вам нужно использовать subprocess.call, который является блокирующим, что означает, что он будет блокировать код обработки до тех пор, пока вызов не будет завершен.

Отличный пост по теме:

Блокирующие и неблокирующие вызовы подпроцессов

person ex4    schedule 04.03.2021
comment
Странно то, что os.system также блокируется, поэтому он также должен дождаться завершения внешнего скрипта. Где-то еще что-то не так... - person sabik; 04.03.2021
comment
@sabik, как дождаться завершения работы os.system? Потому что цикл работает, только если я добавляю time.sleep(x), но мне это не нравится... - person SirLancillotto; 04.03.2021
comment
Вам уже было указано в нескольких комментариях: os.system() уже делает именно это. Если скрипт, который вы запускаете в подпроцессе, продолжает выполнять что-то в фоновом подпроцессе после завершения и отчитывается перед Python, нет простого способа узнать, когда это действительно выполнено. Насколько вопрос четко определен, подпроцесс, который вы явно вызываете, завершается, когда os.system() возвращается. - person tripleee; 04.03.2021