Индикатор выполнения в Sublime Text с Python

Я использую мощный редактор Sublime Text 3 на MacOSX для запуска кодов python. Я хочу отобразить индикатор выполнения цикла for и следующую команду:

sys.stdout.write('rProgress : %03.2f %%' % (100*float(i)/(N)))
sys.flush()

не очищает ранее напечатанную строку в окне вывода, Как ожидалось (r), но производит N строки:

Progress : 0.25 %
Progress : 0.50 %
Progress : 0.75 %
Progress : 1.00 %
Progress : 1.25 %
Progress : 1.50 %
Progress : 1.75 %
Progress : 2.00 %
Progress : 2.25 %
Progress : 2.50 %
...

что не очень приятно читать – я делаю вывод, что окно вывода может быть только для чтения.

есть ли у кого-нибудь предложения по улучшению использования прогресс-бары в Sublime Text?

6 ответов


посмотреть sublime.py мы видим, что flush метод фактически ничего не делает:

class _LogWriter:
    def flush(self):
        pass

    def write(self, s):
        sublime_api.log_message(s)

sys.stdout = _LogWriter()
sys.stderr = _LogWriter()

однако я бы не рекомендовал использовать консоль для пользовательских выходов в любом случае. Обычно вы используете панели вывода / представления или сообщения о состоянии.

сообщения о состоянии проще в использовании, но менее мощные. sergioFC продемонстрировал это в ответ.

это демонстрирует, как использовать панель вывода. Это очень гибкий, но вы должны написать свой собственный текст команда для вставки текста. Это необходимо, поскольку для изменения содержимого представления требуется объект редактирования.

import sublime
import sublime_plugin


class MyInsertProgressBarCommand(sublime_plugin.TextCommand):
    def run(self, edit, value):
        view = self.view
        width, _ = view.viewport_extent()
        em_width = view.em_width()
        # the number of columns are the width divided by the width of a char
        # subtract two to add a little border
        columns = int(width / em_width) - 2

        # subtract two, because we surround it with [ and ]
        bar_length = columns - 2
        # calculate the size of the filled and the remaining part
        filled_length = int(bar_length * value / 100)
        remaining_length = bar_length - filled_length
        # assemble the string for the progress bar
        text = "[{0}{1}]\n".format("=" * filled_length, "." * remaining_length)
        # add the text for the percentages
        if value >= 100:
            percentage_text = "finished!"
        else:
            percentage_text = "{:3.2f} %".format(value)
        text += " " * (columns - len(percentage_text)) + percentage_text

        # replace the content of the view
        view.replace(edit, sublime.Region(0, view.size()), text)
        # reset sels
        view.sel().clear()
        view.sel().add(sublime.Region(0, 0))


class ProgressBarCommand(sublime_plugin.WindowCommand):
    def run(self):
        self.window.create_output_panel("progess_bar")
        self.window.run_command("show_panel", {"panel": "output.progess_bar"})

        def test_progress_bar():
            import random
            test_progress_bar.value += 2 * random.random()
            if test_progress_bar.value >= 100:
                self.finish_progress()
                return
            self.show_progress(test_progress_bar.value)

            sublime.set_timeout(test_progress_bar, 100)
        test_progress_bar.value = 0

        sublime.set_timeout_async(test_progress_bar, 1)

    def show_progress(self, progess):
        view = self.window.find_output_panel("progess_bar")
        view.run_command("my_insert_progress_bar", {"value": progess})

    def finish_progress(self):
        self.show_progress(100)
        sublime.set_timeout(self._destroy, 5000)

    def _destroy(self):
        self.window.destroy_output_panel("progess_bar")

вывод:

Progress bar


вы можете создать визуальный индикатор выполнения, используя:



демо:

Demo



код:

@ На GitHub

( запустите плагин, введя Progress Bar Demo @ палитра команд)

   



Примечания:

есть css файл, который контролирует стиль mdpopups. По какой-то причине color свойство не оказывает никакого эффекта.

и mdpopups.show_popup ' s


как еще одно альтернативное решение вы можете использовать строку состояния. При установке сообщения строки состояния предыдущий текст очищается. контрольный пакет также используется в строке состояния при установке пакетов.

пример:

Sublime text progress bar using status bar

import sublime, sublime_plugin
import time

class ExampleCommand(sublime_plugin.WindowCommand):
    def run(self, args):
        sublime.set_timeout_async(self.test,1)

    def test(self):
        i=80
        while i <= 100:
            sublime.status_message('%03.2f %%' % i)
            time.sleep(0.15)
            i+=0.25
        sublime.status_message('100% Stackoverflow!')

то, что вы можете искать, - это способ сохранить вывод от потребления нескольких строк. Вы можете распечатать \b (символ backspace) столько раз, сколько было ранее напечатанных символов. Я написал это в качестве примера:

(Python 2.7.6)

from __future__ import print_function
import time, sys

for i in range(1, 6):
    print(i, end='')
    sys.stdout.flush()
    time.sleep(0.5)
    print('\b', end='')

попробуйте запустить это, и вы можете адаптировать его к своим потребностям.


вы можете использовать библиотеку progressbar. находится здесь : https://pypi.python.org/pypi/progressbar/2.3-dev

также вы можете установить его из easy_install просто введите:easy_install progressbar

пример использования :

Если вы хотите простой progressbar с информацией о функции:

from progressbar import *
from time import sleep

progress = ProgressBar()
for i in progress(range(80)):
  sleep(0.01)

else если вы хотите progressbar с информацией о функции:

from progressbar import *
from time import sleep

widgets = ['Something: ', Percentage(), ' ', Bar(marker=RotatingMarker()),
           ' ', ETA(), ' ', FileTransferSpeed()]
pbar = ProgressBar(widgets=widgets, maxval=10000000).start()
for i in range(1000000):
  # do something
  pbar.update(10*i+1)
  sleep(0.000001)
pbar.finish()

к сожалению, это невозможно в выходной панели Sublime. Панель не является истинной консолью или терминалом, и среди других различий не интерпретирует escape-последовательности, такие как \r и \b (\n и правильно интерпретированы). Если вы хотите посмотреть, как именно это работает, установите PackageResourceViewer, затем откройте Packages/Default/exec.py.

чтобы заставить это работать, вам нужно создать новый построить систему запустить его в Терминал. Из-за капризов OS X вам нужно будет создать два файла. Первый скрипт:

#!/bin/sh
osascript -e '    
  on run parameters        
    tell application "Terminal"            
      activate            
      do script with command "/path/to/python " & parameters        
    end tell    
  end run
' $@

изменить /path/to С вашим фактическим путем к python (или python3). Сохраните его, где вы хотите, как PythonTerminal.sh. Далее выберите Tools -> Build System -> New Build System и вставьте следующее:

{
    "cmd": ["/bin/sh /path/to/Python3Terminal.sh \"$file\""],
    "file_regex": "^[ ]*File \"(...*?)\", line ([0-9]*)",
    "selector": "source.python",
    "shell": true
}

еще раз, изменить /path/to к фактическому пути к PythonTerminal.sh. Сохраните файл как Packages/User/PythonTerminal.sublime-build (он должен автоматически открывать нужный каталог при экономия.)

наконец, выберите Tools -> Build System -> PythonTerminal, переключитесь на файл Python и создайте с помощью B. Откроется новое окно терминала, и ваш индикатор выполнения должен работать.