Ответ 1
Попробуйте использовать os.system
:
os.system("script2.py 1")
execfile
отличается тем, что предназначен для запуска последовательности инструкций Python в текущем контексте выполнения. Вот почему sys.argv
не изменился для вас.
Я хочу запустить Python script из другого Python script. Я хочу передать переменные, как я бы использовал в командной строке.
Например, я бы запускал свой первый script, который перебирал бы список значений (0,1,2,3) и передавал их во второй script script2.py 0
, затем script2.py 1
и т.д.
Я нашел SO 1186789, который является аналогичным вопросом, но ars отвечает на вызовы функции, где, поскольку я хочу запустить целую script не только функцию, а вызов balpha вызывает script, но без аргументов. Я изменил это на что-то вроде ниже в качестве теста:
execfile("script2.py 1")
Но он не принимает правильные значения. Когда я печатаю sys.argv
в файле script2.py, это первоначальный командный вызов с первым script "['C:\script1.py'].
Я не хочу менять исходный script (т.е. script2.py в моем примере), так как я его не владею.
Я полагаю, что должен быть способ сделать это, я просто смущен, как вы это делаете.
Попробуйте использовать os.system
:
os.system("script2.py 1")
execfile
отличается тем, что предназначен для запуска последовательности инструкций Python в текущем контексте выполнения. Вот почему sys.argv
не изменился для вас.
Это по своей сути неправильная вещь. Если вы используете Python script из другого Python script, вы должны общаться через Python, а не через ОС:
import script1
В идеальном мире вы можете напрямую вызвать функцию внутри script1
:
for i in range(whatever):
script1.some_function(i)
При необходимости вы можете взломать sys.argv
. Там аккуратный способ сделать это с помощью диспетчера контекста, чтобы гарантировать, что вы не вносите никаких постоянных изменений.
import contextlib
@contextlib.contextmanager
def redirect_argv(num):
sys._argv = sys.argv[:]
sys.argv=[str(num)]
yield
sys.argv = sys._argv
with redirect_argv(1):
print(sys.argv)
Я думаю, что это предпочтительнее передавать все ваши данные в ОС и обратно; это просто глупо.
В идеале, Python script, который вы хотите запустить, будет настроен с кодом вроде этого ближе к концу:
def main(arg1, arg2, etc):
# do whatever the script does
if __name__ == "__main__":
main(sys.argv[1], sys.argv[2], sys.argv[3])
Другими словами, если модуль вызывается из командной строки, он анализирует параметры командной строки, а затем вызывает другую функцию main()
, чтобы выполнить фактическую работу. (Фактические аргументы будут различаться, и синтаксический анализ может быть более задействован.)
Если вы хотите вызвать такой script из другого Python script, вы можете просто import
его и вызвать modulename.main()
напрямую, а не проходить через операционную систему.
os.system
будет работать, но это круговой (читай "медленный" ) способ сделать это, так как вы начинаете новый процесс интерпретации Python каждый раз, чтобы не было изюма.
Модуль SubProcess:
http://docs.python.org/dev/library/subprocess.html#using-the-subprocess-module
import subprocess
subprocess.Popen("script2.py 1", shell=True)
С этим вы также можете перенаправить stdin, stdout и stderr.
Я думаю, что хорошая практика может быть чем-то вроде этого;
import subprocess
cmd = 'python script.py'
p = subprocess.Popen(cmd, stdout=subprocess.PIPE, shell=True)
out, err = p.communicate()
result = out.split('\n')
for lin in result:
if not lin.startswith('#'):
print(lin)
согласно документации Модуль подпроцесса позволяет создавать новые процессы, подключаться к их каналам ввода/вывода/ошибок и получать коды возврата. Этот модуль намерен заменить несколько более старых модулей и функций:
os.system
os.spawn*
os.popen*
popen2.*
commands.*
Используйте функцию связи(), а не .stdin.write,.stdout.read или .stderr.read, чтобы избежать взаимоблокировок из-за того, что любой из других буферов буферов ОС заполняет и блокирует дочерний процесс. Читать здесь
import subprocess
subprocess.call(" python script2.py 1", shell=True)
Если os.system недостаточно мощна для вас, модуль подпроцесса.