pythonironpythonrevitpythonshell

Is there a way to get Revit Python Shell not to buffer the print statement?


Is there a way to get Revit Python Shell not to buffer the print statement?

For example, with this code, it is clear to see that RPS will not show anything on the screen until after the loop has finished. Which I am assuming is the result of RPS buffering the output of the print statement.

for i in range(1, 100):
  print i
  time.sleep(1)

While this OK for most things I work on, this behavior will not work for this project...

Here is a quick overview of the project code:

Start ACC (AcCoreConsole) program using popen
for file in filelist:
  send file name to ACC for processing via the input Pipe (a file)
  read results from ACC via the output Pipe (a file).
  (the above steps are working ok)
  print results to Revit Python Shell's screen.
Close ACC

Again nothing shows on the RPS's screen until after the loop is done.

If I can not shut down or reduce the buffering, perhaps there is a different approach I could use? Maybe something other than "print"? Or perhaps, a dedicated output window?

Sincerely; Michelle


Solution

  • Try one of following methods,

    1. Use the RPS output window directly:

      from rpw.ui.forms import Alert
      import time
      
      for i in range(1, 100):
          Alert('Processing: {}'.format(i))  # Shows a popup for each iteration
          time.sleep(1)
      

      Write to the Revit journal file:

      from Autodesk.Revit import UI
      import time
      
      uidoc = __revit__.ActiveUIDocument
      
      for i in range(1, 100):
          UI.TaskDialog.Show("Status", "Processing: {}".format(i))
          time.sleep(1)
      
    2. For Your Specific ACC Project

      Try this approach

      import sys
      import subprocess
      import time
      
      # Start ACC process with unbuffered output
      acc_process = subprocess.Popen(['AcCoreConsole.exe'], 
                                    stdin=subprocess.PIPE,
                                    stdout=subprocess.PIPE,
                                    stderr=subprocess.PIPE,
                                    bufsize=0,  # No buffering
                                    universal_newlines=True)
      
      for file in filelist:
          # Send to ACC
          acc_process.stdin.write(file + '\n')
          acc_process.stdin.flush()
      
          # Read output
          while True:
              output = acc_process.stdout.readline()
              if output == '':
                  break
              print(output.strip())
              sys.stdout.flush()
      
          time.sleep(0.1)  # Small delay if needed
      
      acc_process.stdin.close()
      acc_process.terminate()
      
    3. creating a modeless form:

      from rpw.ui.forms import FlexForm, Label, Button
      import clr
      clr.AddReference('System.Windows.Forms')
      from System.Windows.Forms import Form, TextBox, DockStyle, FormBorderStyle
      
      output_form = Form()
      output_form.Text = "Processing Output"
      output_form.Width = 600
      output_form.Height = 400
      
      text_box = TextBox()
      text_box.Multiline = True
      text_box.Dock = DockStyle.Fill
      text_box.ScrollBars = System.Windows.Forms.ScrollBars.Vertical
      output_form.Controls.Add(text_box)
      
      output_form.Show()
      
      for i in range(1, 100):
          text_box.AppendText("Processing item {}\n".format(i))
          System.Windows.Forms.Application.DoEvents()  # Keep form responsive
          time.sleep(1)