在后台执行外部Python文件并在Python中获得输出

在后台执行外部Python文件并在Python中获得输出,python,subprocess,stdout,execute,Python,Subprocess,Stdout,Execute,我有一个python文件,它接受一些输入并根据这些输入打印输出。我正在尝试在另一个脚本中执行此脚本。我需要做的就是向这个文件发送一些参数,并在这个脚本中获得输出 我需要执行的脚本: while True: print("Sabah 1") print("Oglen 2") print("Aksam 3") print("Gece 4") print("---------") secim = raw_input("Gun icerisindeki zaman dilim

我有一个python文件,它接受一些输入并根据这些输入打印输出。我正在尝试在另一个脚本中执行此脚本。我需要做的就是向这个文件发送一些参数,并在这个脚本中获得输出

我需要执行的脚本:

while True:
  print("Sabah 1")
  print("Oglen 2")
  print("Aksam 3")
  print("Gece 4")
  print("---------")


  secim = raw_input("Gun icerisindeki zaman dilimini giriniz")

  isim = raw_input("Isminizi giriniz.")


  if (secim=='1') : 
      print("Gunaydin"+isim)
  elif (secim == '2'):
      print("Tunaydin"+isim)
  elif (secim == '3'):
      print("iyi aksamlar"+isim)
  elif (secim == '4'):
      print("Iyi geceler"+isim)
  else:
      print("Program sonlandiriliyor")
      break
应执行上述脚本的脚本:

import subprocess, threading, time
can_break = False

def run():
    args = ['python','odev2.py','arg1','arg2']
    popen = subprocess.Popen(args,shell=False,stdout=subprocess.PIPE)
    while not can_break:
        print(popen.stdout.readline())


t = threading.Thread(target=run)

try:
    t.start()
    while True: 
        print('Main Thread.... ')
        time.sleep(1)
except KeyboardInterrupt:
    can_break_break = True
问题是第二个脚本的输出继续打印“主线程…”,我无法读取任何输出


谢谢。

我想您可能想知道为什么看不到odev2.py中的任何提示

简单的回答是将run替换为:

def run():
    args = ['python','-u','odev2.py','arg1','arg2']
    popen = subprocess.Popen(args,shell=False,stdout=subprocess.PIPE)
    while not can_break:
        sys.stdout.write(popen.stdout.read(1))
答案很长,有两个问题

首先是缓冲。IO是昂贵的,因此,文件对象有时会收集缓冲区中的数据,而不是立即写出数据,并且只在缓冲区已满时才写出数据。内置文件对象(如sys.stdout)将根据写入的内容决定缓冲区。如果它们正在向终端写入数据,那么它们将关闭缓冲,以便立即将输出发送给用户。但是,如果他们正在写入文件,他们将使用缓冲区来提高效率

因此,当您在命令行上运行odev2.py时,print正在写入终端,因此它是无缓冲的,提示会立即出现。但是,当您使用子流程(stdout=PIPE)运行odev2.py时,odev2.py将获得一个管道作为标准输出,以便文件对象缓冲。这意味着您看不到提示

使用“python odev2.py arg1 arg2 | cat”可以从命令行中看到运行odev2.py的相同效果。这将标准输出设置为管道,您不会看到任何提示,但odev2.py将等待您键入

通过让odev2.py自己编写提示(而不是让原始输入打印它们),然后在适当的时间调用sys.stdout.flush(),可以解决此缓冲问题。但一种快速而肮脏的方法是使用-u标志运行python,该标志关闭所有缓冲。请尝试“python-u odev2.py arg1 arg2 | cat”查看差异

注意:-u关闭所有缓冲,这会对性能产生巨大影响。所以这只是一个快速而肮脏的解决方案

其次,您的阅读线程使用readline。readline在看到换行符之前不会返回,但odev2.py的提示不会以换行符结束。因此,在odev2.py发送新行之前,运行中的readline不会返回,但是odev2在从您处读取一些输入之前不会发送新行。所以你陷入僵局了


对此,健壮的解决方案是用非阻塞IO替换readline,该IO将返回可用的内容。但在Python2.7中,这是一种可移植的方法。所以快速破解就是进行单字符读取。因此,您不必执行popen.stdout.readline(),只需执行popen.stdout.read(1)。

我想您可能想知道,为什么看不到来自odev2.py的任何提示

简单的回答是将run替换为:

def run():
    args = ['python','-u','odev2.py','arg1','arg2']
    popen = subprocess.Popen(args,shell=False,stdout=subprocess.PIPE)
    while not can_break:
        sys.stdout.write(popen.stdout.read(1))
答案很长,有两个问题

首先是缓冲。IO是昂贵的,因此,文件对象有时会收集缓冲区中的数据,而不是立即写出数据,并且只在缓冲区已满时才写出数据。内置文件对象(如sys.stdout)将根据写入的内容决定缓冲区。如果它们正在向终端写入数据,那么它们将关闭缓冲,以便立即将输出发送给用户。但是,如果他们正在写入文件,他们将使用缓冲区来提高效率

因此,当您在命令行上运行odev2.py时,print正在写入终端,因此它是无缓冲的,提示会立即出现。但是,当您使用子流程(stdout=PIPE)运行odev2.py时,odev2.py将获得一个管道作为标准输出,以便文件对象缓冲。这意味着您看不到提示

使用“python odev2.py arg1 arg2 | cat”可以从命令行中看到运行odev2.py的相同效果。这将标准输出设置为管道,您不会看到任何提示,但odev2.py将等待您键入

通过让odev2.py自己编写提示(而不是让原始输入打印它们),然后在适当的时间调用sys.stdout.flush(),可以解决此缓冲问题。但一种快速而肮脏的方法是使用-u标志运行python,该标志关闭所有缓冲。请尝试“python-u odev2.py arg1 arg2 | cat”查看差异

注意:-u关闭所有缓冲,这会对性能产生巨大影响。所以这只是一个快速而肮脏的解决方案

其次,您的阅读线程使用readline。readline在看到换行符之前不会返回,但odev2.py的提示不会以换行符结束。因此,在odev2.py发送新行之前,运行中的readline不会返回,但是odev2在从您处读取一些输入之前不会发送新行。所以你陷入僵局了


对此,健壮的解决方案是用非阻塞IO替换readline,该IO将返回可用的内容。但在Python2.7中,这是一种可移植的方法。所以快速破解就是进行单字符读取。因此,您不必执行popen.stdout.readline(),只需执行popen.stdout.read(1)。

Thabk您是非常好的朋友。Thabk您是非常好的朋友。