Home Download Buy Blog Forum Support

Execute external program in background (non-blocking thread)

Execute external program in background (non-blocking thread)

Postby Sha1 on Sun Aug 18, 2013 5:47 pm

Good time of day everyone.
I want to create plugin for ST3. But I am not familar with Python3. I decided to write it in other script language. So, I need code snippet to run my script (external program) in backround mode and to do something when script is finished.

I have:
Code: Select all
class FuncThread(threading.Thread):
   def __init__(self, target):
      self._target = target
      threading.Thread.__init__(self)

   def run(self):
      self._target()


Somewhere in "run"
Code: Select all
thread = threading.Thread(target = my_long_calculate, args = (self.view, edit))
thread.start()


my_long_calculate looks approximately as:
Code: Select all
subprocess.Popen(cmd, stdout=subprocess.PIPE, startupinfo=startupinfo).communicate()[0]


But my ST still is hanging (locked) when my_long_calculate() is running.
What am I doing wrong?
Sha1
 
Posts: 4
Joined: Fri Nov 23, 2012 4:07 pm

Re: Execute external program in background (non-blocking thread)

Postby Veedrac on Sun Aug 18, 2013 6:07 pm

What on earth are you doing that would make it easier to shell out to a different process than to clutz through Python?

Also, how are you planning to turn the script's output into changes to Sublime Text?
Veedrac
 
Posts: 19
Joined: Sun Aug 18, 2013 4:16 pm

Re: Execute external program in background (non-blocking thread)

Postby Sha1 on Sun Aug 18, 2013 6:31 pm

It is not easier! I told that I dont known python (I dont understand languages without curly brackets). I'm sure that my task can be solved in Python, but I dont know it, everything is simple.

Also, how are you planning to turn the script's output into changes to Sublime Text?

This is example ST3 plugin "Hello from node.js"
https://gist.github.com/unlight/6262932

run view.run_command("hello_node") command in ST console.
Sha1
 
Posts: 4
Joined: Fri Nov 23, 2012 4:07 pm

Re: Execute external program in background (non-blocking thread)

Postby sapphirehamster on Sun Aug 18, 2013 8:06 pm

You don't really show enough code to see what is wrong. Also, you are not supposed to retain or pass the "edit" object between threads. Instead, call view.run_command of a second TextCommand that will apply the appropriate changes.

As an aside, using the sublime.set_timeout_async function might be simpler than manually creating a thread.
sapphirehamster
 
Posts: 90
Joined: Sun Jul 01, 2012 11:19 pm

Re: Execute external program in background (non-blocking thread)

Postby Sha1 on Sun Aug 18, 2013 9:28 pm

@sapphirehamster
I upload full code of test plugin on github: https://github.com/unlight/HelloNode
I used
Code: Select all
sublime.set_timeout_async(lambda: self.view.run_command("long_loop"), 0)


In long_loop command occurs "long calculation" which I emulate by Javascript setTimeout() function, and in this time ST3 is "hanging" (cannot move cursor, cannot write something, etc.)
Sha1
 
Posts: 4
Joined: Fri Nov 23, 2012 4:07 pm

Re: Execute external program in background (non-blocking thread)

Postby sapphirehamster on Mon Aug 19, 2013 7:52 am

I think you may have misunderstood when I said it needs to run a second TextCommand. You need to call set_timeout_async on your own function that will do the long computation, and then call the TextCommand. It would look something roughly like this:

Code: Select all
class ExampleNodeCommand(sublime_plugin.TextCommand):
    def run(self, edit):
        sublime.set_timeout_async(self.long_command, 0)

    def long_command(self):
        args = [get_node_path(), PLUGIN_FOLDER + "/longloop.js"]
        for region in self.view.sel():
            output = run_process(args)
            pos = region.begin()
            self.view.run_command('example_node2', {'pos': pos, 'output': output})

class ExampleNode2Command(sublime_plugin.TextCommand):
    def run(self, edit, pos=None, output=None):
        self.view.insert(edit, pos, output)


I didn't test this, so there may be typos, but it's the general idea. Also, you may have problems if there are multiple cursors (the positions may shift, so you may want to iterate over the Selection in reverse).
sapphirehamster
 
Posts: 90
Joined: Sun Jul 01, 2012 11:19 pm

Re: Execute external program in background (non-blocking thread)

Postby Sha1 on Sat Aug 24, 2013 8:49 pm

Nice. It works! Thank you very much.
Sha1
 
Posts: 4
Joined: Fri Nov 23, 2012 4:07 pm

Re: Execute external program in background (non-blocking thread)

Postby badsyntax on Mon Sep 16, 2013 8:24 pm

sapphirehamster wrote:...You need to call set_timeout_async on your own function that will do the long computation, and then call the TextCommand.


thank you for your comment and example code, this has been very helpful for me! kudos!
badsyntax
 
Posts: 3
Joined: Wed May 22, 2013 9:28 pm


Return to Plugin Development

Who is online

Users browsing this forum: buzzsawddog and 9 guests