带有 Python 的 Sublime Text 中的进度条
Progress bar in Sublime Text with Python
我在 MacOSX 上使用功能强大的 Sublime Text 3 编辑器来编写 运行 python 代码。我想显示一个for循环的进度条,命令如下:
sys.stdout.write('\rProgress : %03.2f %%' % (100*float(i)/(N)))
sys.flush()
未按预期清除输出 window 中先前打印的行 (\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 %
...
读起来不太好——我得出结论,输出 window 可能是只读的。
有没有人有改进 Sublime Text 中进度条使用的建议?
您可能正在寻找一种避免输出占用多行的方法。您可以打印 \b
(退格字符)与之前打印的字符一样多。我写这个作为例子:
(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='')
尝试 运行,您可以根据自己的需要进行调整。
不幸的是,这在 Sublime 的输出面板中是不可能的。该面板不是真正的控制台或终端,除其他差异外,不解释转义序列,例如 \r
和 \b
(\n
是 解释但是正确)。如果你想看看它是如何工作的,安装 PackageResourceViewer
,然后打开 Packages/Default/exec.py
.
为了让它工作,您需要在终端中创建一个新的 build system 到 运行 它。由于 OS X 的变幻莫测,您需要创建两个文件。第一个是 shell 脚本:
#!/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
。接下来,select 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
(保存时应该会自动打开正确的目录)。
最后,selectTools -> Build System -> PythonTerminal
,切换到你的Python文件,用⌘[=46构建=]B。一个新终端 window 将打开,您的进度条应该 运行.
作为另一种替代解决方案您可以使用状态栏。当您设置状态栏消息时,先前的文本将被清除。 包控制 安装包时也使用状态栏。
示例:
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% Whosebug!')
看看 sublime.py
我们发现 flush
方法实际上什么都不做:
class _LogWriter:
def flush(self):
pass
def write(self, s):
sublime_api.log_message(s)
sys.stdout = _LogWriter()
sys.stderr = _LogWriter()
但是无论如何我都不建议使用控制台进行用户输出。通常您使用输出 panels/views 或状态消息。
状态消息更易于使用,但功能较弱。 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")
输出:
您可以使用以下方法创建可视进度条:
- mdpopups 图书馆
sublime.set_timeout
或 sublime.set_timeout_async
(参见:Sublime Module)
演示:
代码:
@ GitHub
(运行 通过在命令面板输入 Progress Bar Demo
插件)
备注:
有一个css file控制着mdpopups
的样式。
出于某种原因,color
属性 没有任何效果。
此外,mdpopups.show_popup
的 location
参数需要 -1
以便在插入符号位置设置弹出窗口。
否则,我不确定 location
如何影响弹出窗口,因为它只需要一个整数值。
我已经在以下线程中询问了这些问题:
[Proof Of Concept] Visual Progress Bar
您可以使用进度条库。位于此处:https://pypi.python.org/pypi/progressbar/2.3-dev
您也可以从 easy_install 安装它,只需键入:easy_install progressbar
使用示例:
如果您想要简单的进度条而不需要有关功能的信息:
from progressbar import *
from time import sleep
progress = ProgressBar()
for i in progress(range(80)):
sleep(0.01)
否则,如果您想要带有有关函数信息的进度条:
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()
我在 MacOSX 上使用功能强大的 Sublime Text 3 编辑器来编写 运行 python 代码。我想显示一个for循环的进度条,命令如下:
sys.stdout.write('\rProgress : %03.2f %%' % (100*float(i)/(N)))
sys.flush()
未按预期清除输出 window 中先前打印的行 (\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 %
...
读起来不太好——我得出结论,输出 window 可能是只读的。
有没有人有改进 Sublime Text 中进度条使用的建议?
您可能正在寻找一种避免输出占用多行的方法。您可以打印 \b
(退格字符)与之前打印的字符一样多。我写这个作为例子:
(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='')
尝试 运行,您可以根据自己的需要进行调整。
不幸的是,这在 Sublime 的输出面板中是不可能的。该面板不是真正的控制台或终端,除其他差异外,不解释转义序列,例如 \r
和 \b
(\n
是 解释但是正确)。如果你想看看它是如何工作的,安装 PackageResourceViewer
,然后打开 Packages/Default/exec.py
.
为了让它工作,您需要在终端中创建一个新的 build system 到 运行 它。由于 OS X 的变幻莫测,您需要创建两个文件。第一个是 shell 脚本:
#!/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
。接下来,select 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
(保存时应该会自动打开正确的目录)。
最后,selectTools -> Build System -> PythonTerminal
,切换到你的Python文件,用⌘[=46构建=]B。一个新终端 window 将打开,您的进度条应该 运行.
作为另一种替代解决方案您可以使用状态栏。当您设置状态栏消息时,先前的文本将被清除。 包控制 安装包时也使用状态栏。
示例:
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% Whosebug!')
看看 sublime.py
我们发现 flush
方法实际上什么都不做:
class _LogWriter:
def flush(self):
pass
def write(self, s):
sublime_api.log_message(s)
sys.stdout = _LogWriter()
sys.stderr = _LogWriter()
但是无论如何我都不建议使用控制台进行用户输出。通常您使用输出 panels/views 或状态消息。
状态消息更易于使用,但功能较弱。 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")
输出:
您可以使用以下方法创建可视进度条:
- mdpopups 图书馆
sublime.set_timeout
或sublime.set_timeout_async
(参见:Sublime Module)
演示:
代码:
@ GitHub
(运行 通过在命令面板输入 Progress Bar Demo
插件)
备注:
有一个css file控制着mdpopups
的样式。
出于某种原因,color
属性 没有任何效果。
此外,mdpopups.show_popup
的 location
参数需要 -1
以便在插入符号位置设置弹出窗口。
否则,我不确定 location
如何影响弹出窗口,因为它只需要一个整数值。
我已经在以下线程中询问了这些问题:
[Proof Of Concept] Visual Progress Bar
您可以使用进度条库。位于此处:https://pypi.python.org/pypi/progressbar/2.3-dev
您也可以从 easy_install 安装它,只需键入:easy_install progressbar
使用示例:
如果您想要简单的进度条而不需要有关功能的信息:
from progressbar import *
from time import sleep
progress = ProgressBar()
for i in progress(range(80)):
sleep(0.01)
否则,如果您想要带有有关函数信息的进度条:
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()