2013-02-21 3 views
1

Я создаю скрипт python, который захватывает информацию из API и создает контекстное меню, которое дает вам доступ к ним. Я хочу использовать потоки, поскольку он работает немного медленнее при одном вызове API, но я не уверен, как реализовать потоки с моим кодом. Я использую этот сайт для ссылки на threading: http://www.ibm.com/developerworks/aix/library/au-threadingpython/ Я понимаю логику в коде, я просто не хочу писать класс потоковой передачи для каждого метода, который я хочу использовать в потоке.Python threading in for loop

Вот класс, который создает контекстное меню, а затем анализирует возвращаемый json, я думаю, я должен добавить его в цикл for в команде run. Любая помощь приветствуется.

class SyncsnippetsCommand(sublime_plugin.TextCommand): 

    def __init__(self, queue): 
     threading.Thread.__init__(self) 
     self.queue = queue 

    def buildLexerDict(self,snippets): 
     lexers = snippets[0]['user']['lexers'] 
     lexer_dict = {} 
     for lexer in lexers: 
      lexer_dict[lexer] = [] 
     return lexer_dict 

    def buildsnippetsContextDict(self,snippets,lexer_dict): 
     snippets_dict = lexer_dict 
     for snippet in snippets: 
      snippets_dict[snippet['lexer']].append({"id":str(snippet['id']), 
             "title":snippet['title']}) 
     return snippets_dict 

    def run(self, edit): 
     snippet_url = buildsnippetURL() 
     snippets_count = 1; 
     snippets = getsnippets(snippet_url) 
     context_menu = '[' 
     context_menu += '\n\t{ "caption": "snippets", "id": "file", "children":' 
     context_menu += '\n\t\t[' 
     if snippets == None: 
      {"caption":"No snippets available"} 
     else: 
      snippets = snippets['objects'] 
      lexers = self.buildLexerDict(snippets) 
      snippets_dict = self.buildsnippetsContextDict(snippets, lexers) 
      for j,key in reversed(list(enumerate(reversed(snippets_dict.keys())))): 
       ... loop through JSON and create menu ... 
       if j == 0: 
        context_menu += '' 
       else: 
        context_menu += ',' 
     context_menu += '\n\t\t]' 
     context_menu += '\n\t}' 
     context_menu += '\n]' 
     f = open(sublime.packages_path() + '\snippetSync\\Context.sublime-menu', 'w') 
     f.write(context_menu) 
     f.close 
     self.view.set_status('snippet', 'snippet Sync: Added ' + str(snippets_count) + ' snippets from your account.') 
     sublime.set_timeout(lambda: self.view.erase_status('snippet'), 3000) 
     return 
+0

threading.Thread должен быть базовым классом для SyncsnippetsCommand, но вы включили только sublime_plugin.TextCommand. Я только немного играл с потоками, поэтому могут быть исключения, о которых я не знаю. – Octipi

+0

Я ценю понимание и понимаю, что - вы увидите, что я действительно не реализовал потоки, поскольку я ищу лучший подход к моему конкретному сценарию. Благодарю. – gregwhitworth

ответ

2

Вот простой плагин Sublime Text 2 с резьбой. Что он делает, это вставить Hello World! через 3 секунды. Вы заметите, что вы можете перемещать курсор в течение этих трех секунд.

В вашем случае, похоже, вам просто нужно захватить кучу фрагментов из API и создать контекстное меню из возвращаемых данных. Затем появится уведомление, в котором рассказывается, сколько фрагментов было добавлено. Я мог ошибаться, но вы должны иметь возможность изменить этот код, чтобы заставить ваш плагин работать.

import threading 
import time 
import sublime 
import sublime_plugin 

""" 
The command just creates and runs a thread. 
The thread will do all the work in the background. 

Note that in your Thread constructor, you will need to pass in an 
instance of your Command class to work with in your thread. 
""" 
class ExampleCommand(sublime_plugin.TextCommand): 

    def run(self, edit): 

     exampleThread = ExampleThread(self, edit) 
     exampleThread.start() 

""" 
Extend the Thread class and add your functionality in 
the run method below. 

One thing to remember when moving your code over is 
you need to use self.cmd instead of self. 
""" 
class ExampleThread(threading.Thread): 

    """ 
    Remember to pass in the parameters you need 
    in this thread constructor. 
    """ 
    def __init__(self, cmd, edit): 
     threading.Thread.__init__(self) 
     self.cmd = cmd 
     self.edit = edit 

    """ 
    Add your functionality here. 

    If you need to access the main thread, you need to 
    use sublime.set_timeout(self.callback, 1). 

    In my example here, you can't call insert text into the editor 
    unless you are in the main thread. 

    Luckily that is fast operation. 

    Basically, time.sleep(3) is a slow operation and will block, hence it 
    is run in this separate thread. 
    """ 
    def run(self): 
     time.sleep(3) 
     sublime.set_timeout(self.callback, 1) 

    """ 
    This is the callback function that will be called to 
    insert HelloWorld. 

    You will probably need to use this to set your status message at 
    the end. I'm pretty sure that requires that you be on main thread 
    to work. 
    """ 
    def callback(self): 
     self.cmd.view.insert(self.edit, 0, "Hello, World!") 

Update

я нашел некоторое время интегрировать фрагмент кода выше, используя подход, я описанной выше. Вам все равно нужно заполнить некоторые пробелы, но, надеюсь, это дает вам представление о том, где разместить свой код. Я тестировал, что основной скелет все еще работает, поэтому раздел, в котором вы строите контекстное меню, закомментирован в этом примере.

import threading 
import time 
import sublime 
import sublime_plugin 


def buildsnippetURL(): 
    return "" 

def getsnippets(snippet_url): 
    time.sleep(3) 
    return "" 

class SyncsnippetsCommand(sublime_plugin.TextCommand): 
    def run(self, edit): 
     syncsnippetsThread = SyncsnippetsThread(self, edit) 
     syncsnippetsThread.start() 


class SyncsnippetsThread(threading.Thread): 
    def __init__(self, cmd, edit): 
     threading.Thread.__init__(self) 
     self.cmd = cmd 
     self.edit = edit 

    def buildLexerDict(self,snippets): 
     lexers = snippets[0]['user']['lexers'] 
     lexer_dict = {} 
     for lexer in lexers: 
      lexer_dict[lexer] = [] 
     return lexer_dict 

    def buildsnippetsContextDict(self,snippets,lexer_dict): 
     snippets_dict = lexer_dict 
     for snippet in snippets: 
      snippets_dict[snippet['lexer']].append({"id":str(snippet['id']), 
             "title":snippet['title']}) 
     return snippets_dict 

    def run(self): 
     snippet_url = buildsnippetURL() 
     snippets_count = 1; 
     snippets = getsnippets(snippet_url) 

     """ 
     context_menu = '[' 
     context_menu += '\n\t{ "caption": "snippets", "id": "file", "children":' 
     context_menu += '\n\t\t[' 
     if snippets == None: 
      {"caption":"No snippets available"} 
     else: 
      snippets = snippets['objects'] 
      lexers = self.buildLexerDict(snippets) 
      snippets_dict = self.buildsnippetsContextDict(snippets, lexers) 
      for j,key in reversed(list(enumerate(reversed(snippets_dict.keys())))): 
       ... loop through JSON and create menu ... 
       if j == 0: 
        context_menu += '' 
       else: 
        context_menu += ',' 
     context_menu += '\n\t\t]' 
     context_menu += '\n\t}' 
     context_menu += '\n]' 
     f = open(sublime.packages_path() + '\snippetSync\\Context.sublime-menu', 'w') 
     f.write(context_menu) 
     f.close 
     """ 

     sublime.set_timeout(lambda: self.callback(snippets_count), 1) 

    def callback(self, snippets_count): 
     self.cmd.view.set_status('snippet', 'snippet Sync: Added ' + str(snippets_count) + ' snippets from your account.') 
     sublime.set_timeout(lambda: self.cmd.view.erase_status('snippet'), 3000) 
+0

Значит ли это, что для каждого метода, который требуется для потоковой передачи, мне нужно создать собственный класс для обработки потоков? Спасибо за помощь, как всегда. – gregwhitworth

+0

Это зависит от того, как работает ваш плагин. В этом случае, я думаю, вы можете просто использовать один поток. Подумайте об этом как о блоке кода, который вы хотите выполнить в фоновом режиме. Все, что в методе запуска вашего класса Thread будет запущено в фоновом режиме. Таким образом, вы должны иметь возможность вызывать другие методы/функции. Большей вещью, которой следует следить в поточном программировании, являются конфликты, в которых состояние изменяется в нескольких потоках. В этом случае я не думаю, что это будет проблемой. – Gohn67