Home Download Buy Blog Forum Support

How to see the output of a POpen in a window or console

How to see the output of a POpen in a window or console

Postby DJHoltkamp on Tue Jul 09, 2013 8:33 pm

First off, I'm using Sublime 3 on OSX...

I'm trying to run an outside program and see the output on the console but I can't seem to find a way. Note that I don't want any thread locking as they should still be able to use Sublime while the other command runs. Here is an example of the command:

subprocess.Popen(['moai', 'main.lua'], shell=True, cwd=folder);

It would also be acceptable to pipe this to another view, but I was looking for the easiest solution so I was trying to avoid polling the process' output and writing it manually to a view.

Thanks!
David
DJHoltkamp
 
Posts: 2
Joined: Mon Jul 08, 2013 5:41 pm

Re: How to see the output of a POpen in a window or console

Postby Clams on Wed Jul 10, 2013 7:40 am

Here is a class I used to be able to run some command related to mercurial and display teh result:
Basically you simply redirect the stdout to be able to access it after a wait. Then, once it is done, I display it in a sublimeText Panel. Maybe not exactly what you want ...
Code: Select all
class HgScript :

   # main_thread uses sublime.set_timeout to send things onto the main thread
   # most sublime.[something] calls need to be on the main thread
   ## (Copied from plugin NodeJs by tanepiper) ##
   def main_thread(callback, *args, **kwargs):
        sublime.set_timeout(functools.partial(callback, *args, **kwargs), 0)

   #
   def exec_cmdhg(self, cmd_a, show_stdout=True):
      p = subprocess.Popen(cmd_a, cwd=self.dname,  stdout=subprocess.PIPE, stderr=subprocess.STDOUT, shell=True)
      p.wait()
      if p.stderr is not None :
         stderr_lines = p.stderr.readlines()
         self.print_to_panel(cmd_a[1],stderr_lines)
         return False
      if p.stdout is not None :
         self.exec_msg = p.stdout.readlines()
         if show_stdout :
            self.print_to_panel(cmd_a[1],self.exec_msg)
      return True

   # Show a panel with a message.
   # Apply the diff syntax hilighting if the command run was diff
   def print_to_panel(self,cmd,str_a):
      sublime.set_timeout(lambda: self.print_to_panel_mainthread(cmd,str_a), 0)

   def print_to_panel_mainthread(self,cmd,str_a):
      win = sublime.active_window()
      strtxt = u"".join(line.decode("utf-8") for line in str_a)
      if(len(str_a)):
         v = win.create_output_panel('hg_out')
         if cmd=="diff" :
            v.set_syntax_file('Packages/Diff/Diff.tmLanguage')
            v.settings().set('word_wrap', self.view.settings().get('word_wrap'))
         # edit = v.begin_edit(1,"")
         # v.insert(edit, 0, strtxt)
         # v.end_edit(edit)
         v.run_command('append', {'characters': strtxt})
         win.run_command("show_panel", {"panel": "output.hg_out"})


And to have something non blocking you simply wrap that in a thread:
Code: Select all
#Simple execute file wrapped in a thread
class RunScriptThread(threading.Thread, HgScript):
   def __init__(self, dname,fname,script_name):
      self.dname = dname
      self.fname = fname
      self.script_name = script_name
      threading.Thread.__init__(self)

   def run(self):
      exec(open(self.script_name).read())
Clams
 
Posts: 47
Joined: Fri Dec 30, 2011 7:44 am

Re: How to see the output of a POpen in a window or console

Postby sapphirehamster on Wed Jul 10, 2013 7:58 am

You can just spawn a new thread to run the command in the background (so sublime does not hang). You can either use the threading module or the sublime.set_timeout_async function.

Anything you print() will show up in the console. It's fairly easy to capture the output as a string using the subprocess module. Check the docs as there are multiple ways depending on your needs.

A bare minimum example:
Code: Select all
class ExampleCommand(sublime_plugin.TextCommand):
   def run(self, edit):
      sublime.set_timeout_async(self.doit, 0)

   def doit(self):
      try:
         a = subprocess.check_output(['ls'], stderr=subprocess.STDOUT)
      except subprocess.CalledProcessError as e:
         print(e.output)
      else:
         print(a)
sapphirehamster
 
Posts: 88
Joined: Sun Jul 01, 2012 11:19 pm

Re: How to see the output of a POpen in a window or console

Postby DJHoltkamp on Thu Jul 11, 2013 4:02 pm

Thanks guys; This really helped!

I've come up with code for Sublime 3 (Python 3) that does exactly what I want based on this:

Code: Select all
def RunToConsole(args, current_dir = None):
    sublime.set_timeout_async(lambda: run_in_background(args, current_dir), 0)
   

def run_in_background(args, current_dir):
    proc = ''
    if current_dir is None:
        proc = subprocess.Popen(args, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    else:
        proc = subprocess.Popen(args,  cwd=current_dir, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
    while proc.poll() is None:
        try:
            data = proc.stdout.readline().decode(encoding='UTF-8')
            print(data, end="")
        except:
            print("process ended...")
            return;
    print("process ended...")
DJHoltkamp
 
Posts: 2
Joined: Mon Jul 08, 2013 5:41 pm


Return to Plugin Development

Who is online

Users browsing this forum: No registered users and 2 guests