如何创建旋转的命令行光标?

发布于 2024-10-17 03:40:38 字数 33 浏览 10 评论 0原文

有没有办法使用 Python 在终端中打印旋转光标?

Is there a way to print a spinning cursor in a terminal using Python?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(26

雪化雨蝶 2024-10-24 03:40:38

像这样,假设你的终端处理 \b

import sys
import time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()
for _ in range(50):
    sys.stdout.write(next(spinner))
    sys.stdout.flush()
    time.sleep(0.1)
    sys.stdout.write('\b')

Something like this, assuming your terminal handles \b

import sys
import time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()
for _ in range(50):
    sys.stdout.write(next(spinner))
    sys.stdout.flush()
    time.sleep(0.1)
    sys.stdout.write('\b')
零度° 2024-10-24 03:40:38

易于使用的 API(这将在单独的线程中运行微调器):

import sys
import time
import threading

class Spinner:
    busy = False
    delay = 0.1

    @staticmethod
    def spinning_cursor():
        while 1: 
            for cursor in '|/-\\': yield cursor

    def __init__(self, delay=None):
        self.spinner_generator = self.spinning_cursor()
        if delay and float(delay): self.delay = delay

    def spinner_task(self):
        while self.busy:
            sys.stdout.write(next(self.spinner_generator))
            sys.stdout.flush()
            time.sleep(self.delay)
            sys.stdout.write('\b')
            sys.stdout.flush()

    def __enter__(self):
        self.busy = True
        threading.Thread(target=self.spinner_task).start()

    def __exit__(self, exception, value, tb):
        self.busy = False
        time.sleep(self.delay)
        if exception is not None:
            return False

现在在代码中任意位置的 with 块中使用它:

with Spinner():
  # ... some long-running operations
  # time.sleep(3) 

Easy to use API (this will run the spinner in a separate thread):

import sys
import time
import threading

class Spinner:
    busy = False
    delay = 0.1

    @staticmethod
    def spinning_cursor():
        while 1: 
            for cursor in '|/-\\': yield cursor

    def __init__(self, delay=None):
        self.spinner_generator = self.spinning_cursor()
        if delay and float(delay): self.delay = delay

    def spinner_task(self):
        while self.busy:
            sys.stdout.write(next(self.spinner_generator))
            sys.stdout.flush()
            time.sleep(self.delay)
            sys.stdout.write('\b')
            sys.stdout.flush()

    def __enter__(self):
        self.busy = True
        threading.Thread(target=self.spinner_task).start()

    def __exit__(self, exception, value, tb):
        self.busy = False
        time.sleep(self.delay)
        if exception is not None:
            return False

Now use it in a with block anywhere in the code:

with Spinner():
  # ... some long-running operations
  # time.sleep(3) 
作业与我同在 2024-10-24 03:40:38

一个不错的 Pythonic 方法是使用 itertools.cycle:

import itertools, sys
spinner = itertools.cycle(['-', '/', '|', '\\'])
while True:
    sys.stdout.write(next(spinner))   # write the next character
    sys.stdout.flush()                # flush stdout buffer (actual character display)
    sys.stdout.write('\b')            # erase the last written char

此外,您可能希望在长函数调用期间使用线程来显示微调器,如 http://www.interclasse.com/scripts/spin.php

A nice pythonic way is to use itertools.cycle:

import itertools, sys
spinner = itertools.cycle(['-', '/', '|', '\\'])
while True:
    sys.stdout.write(next(spinner))   # write the next character
    sys.stdout.flush()                # flush stdout buffer (actual character display)
    sys.stdout.write('\b')            # erase the last written char

Also, you might want to use threading to display the spinner during a long function call, as in http://www.interclasse.com/scripts/spin.php

暗恋未遂 2024-10-24 03:40:38

example

为了完整起见,我想添加很棒的包 光环。它提供了大量预设旋转器和更高级别的自定义选项。

从他们的自述文件中摘录

from halo import Halo

spinner = Halo(text='Loading', spinner='dots')
spinner.start()

# Run time consuming work here
# You can also change properties for spinner as and when you want

spinner.stop()

或者,您可以将 halo 与 Python 的 with 语句一起使用:

from halo import Halo

with Halo(text='Loading', spinner='dots'):
    # Run time consuming work here

最后,您可以使用 halo 作为装饰器:

from halo import Halo

@Halo(text='Loading', spinner='dots')
def long_running_function():
    # Run time consuming work here
    pass

long_running_function()

example

For completeness I want to add the great package halo. It offers a lot of preset spinners and higher level customization options.

Extract from their readme

from halo import Halo

spinner = Halo(text='Loading', spinner='dots')
spinner.start()

# Run time consuming work here
# You can also change properties for spinner as and when you want

spinner.stop()

Alternatively, you can use halo with Python's with statement:

from halo import Halo

with Halo(text='Loading', spinner='dots'):
    # Run time consuming work here

Finally, you can use halo as a decorator:

from halo import Halo

@Halo(text='Loading', spinner='dots')
def long_running_function():
    # Run time consuming work here
    pass

long_running_function()
凡间太子 2024-10-24 03:40:38

解决方案:

import sys
import time

print "processing...\\",
syms = ['\\', '|', '/', '-']
bs = '\b'

for _ in range(10):
    for sym in syms:
        sys.stdout.write("\b%s" % sym)
        sys.stdout.flush()
        time.sleep(.5)

关键是使用退格字符“\b”并刷新标准输出。

A solution:

import sys
import time

print "processing...\\",
syms = ['\\', '|', '/', '-']
bs = '\b'

for _ in range(10):
    for sym in syms:
        sys.stdout.write("\b%s" % sym)
        sys.stdout.flush()
        time.sleep(.5)

The key is to use the backspace character '\b' and flush stdout.

与之呼应 2024-10-24 03:40:38

来自 @Victor Moyseenko 的改进版本
因为原始版本几乎没有问题

  1. ,在旋转完成后留下旋转器的字符
  2. ,有时会导致删除后续输出的第一个字符,也
  3. 通过在输出上放置 threading.Lock() 来避免罕见的竞争条件
  4. ,当没有 tty 可用时,会回退到更简单的输出(无旋转)
import sys
import threading
import itertools
import time

class Spinner:

    def __init__(self, message, delay=0.1):
        self.spinner = itertools.cycle(['-', '/', '|', '\\'])
        self.delay = delay
        self.busy = False
        self.spinner_visible = False
        sys.stdout.write(message)

    def write_next(self):
        with self._screen_lock:
            if not self.spinner_visible:
                sys.stdout.write(next(self.spinner))
                self.spinner_visible = True
                sys.stdout.flush()

    def remove_spinner(self, cleanup=False):
        with self._screen_lock:
            if self.spinner_visible:
                sys.stdout.write('\b')
                self.spinner_visible = False
                if cleanup:
                    sys.stdout.write(' ')       # overwrite spinner with blank
                    sys.stdout.write('\r')      # move to next line
                sys.stdout.flush()

    def spinner_task(self):
        while self.busy:
            self.write_next()
            time.sleep(self.delay)
            self.remove_spinner()

    def __enter__(self):
        if sys.stdout.isatty():
            self._screen_lock = threading.Lock()
            self.busy = True
            self.thread = threading.Thread(target=self.spinner_task)
            self.thread.start()

    def __exit__(self, exception, value, tb):
        if sys.stdout.isatty():
            self.busy = False
            self.remove_spinner(cleanup=True)
        else:
            sys.stdout.write('\r')

上面 Spinner 类的使用示例:


with Spinner("just waiting a bit.. "):

        time.sleep(3)

将代码上传到 https:// github.com/Tagar/stuff/blob/master/spinner.py

Improved version from @Victor Moyseenko
as the original version had few issues

  1. was leaving spinner's characters after spinning is complete
  2. and sometimes lead to removing following output's first character too
  3. avoids a rare race condition by putting threading.Lock() on output
  4. falls back to simpler output when no tty is available (no spinning)
import sys
import threading
import itertools
import time

class Spinner:

    def __init__(self, message, delay=0.1):
        self.spinner = itertools.cycle(['-', '/', '|', '\\'])
        self.delay = delay
        self.busy = False
        self.spinner_visible = False
        sys.stdout.write(message)

    def write_next(self):
        with self._screen_lock:
            if not self.spinner_visible:
                sys.stdout.write(next(self.spinner))
                self.spinner_visible = True
                sys.stdout.flush()

    def remove_spinner(self, cleanup=False):
        with self._screen_lock:
            if self.spinner_visible:
                sys.stdout.write('\b')
                self.spinner_visible = False
                if cleanup:
                    sys.stdout.write(' ')       # overwrite spinner with blank
                    sys.stdout.write('\r')      # move to next line
                sys.stdout.flush()

    def spinner_task(self):
        while self.busy:
            self.write_next()
            time.sleep(self.delay)
            self.remove_spinner()

    def __enter__(self):
        if sys.stdout.isatty():
            self._screen_lock = threading.Lock()
            self.busy = True
            self.thread = threading.Thread(target=self.spinner_task)
            self.thread.start()

    def __exit__(self, exception, value, tb):
        if sys.stdout.isatty():
            self.busy = False
            self.remove_spinner(cleanup=True)
        else:
            sys.stdout.write('\r')

example of usage of the Spinner class above:


with Spinner("just waiting a bit.. "):

        time.sleep(3)

uploaded code to https://github.com/Tagar/stuff/blob/master/spinner.py

清风无影 2024-10-24 03:40:38

不错,简单,干净……

while True:
    for i in '|\\-/':
        print('\b' + i, end='')

Nice, simple, and clean...

while True:
    for i in '|\\-/':
        print('\b' + i, end='')
睫毛溺水了 2024-10-24 03:40:38

当然,这是可能的。这只是在四个字符之间打印退格字符 (\b) 的问题,这会使“光标”看起来像在旋转 ( -, \|/)。

Sure, it's possible. It's just a question of printing the backspace character (\b) in between the four characters that would make the "cursor" look like it's spinning ( -, \, |, /).

情场扛把子 2024-10-24 03:40:38

我在 GitHub 上找到了 py-spin 包。它有许多漂亮的旋转款式。这里有一些关于如何使用的示例,Spin1\-/ 样式:

from __future__ import print_function

import time

from pyspin.spin import make_spin, Spin1

# Choose a spin style and the words when showing the spin.
@make_spin(Spin1, "Downloading...")
def download_video():
    time.sleep(10)

if __name__ == '__main__':
    print("I'm going to download a video, and it'll cost much time.")
    download_video()
    print("Done!")
    time.sleep(0.1)

也可以手动控制旋转:

from __future__ import print_function

import sys
import time

from pyspin.spin import Spin1, Spinner

# Choose a spin style.
spin = Spinner(Spin1)
# Spin it now.
for i in range(50):
    print(u"\r{0}".format(spin.next()), end="")
    sys.stdout.flush()
    time.sleep(0.1)

下面的 gif 中的其他样式。

样式在 py-spin 包中旋转。

I have found py-spin package on GitHub. It has many nice spinning Styles. Here are some sample about how to use, Spin1 is the \-/ style:

from __future__ import print_function

import time

from pyspin.spin import make_spin, Spin1

# Choose a spin style and the words when showing the spin.
@make_spin(Spin1, "Downloading...")
def download_video():
    time.sleep(10)

if __name__ == '__main__':
    print("I'm going to download a video, and it'll cost much time.")
    download_video()
    print("Done!")
    time.sleep(0.1)

It is also possible to control the spin manualy:

from __future__ import print_function

import sys
import time

from pyspin.spin import Spin1, Spinner

# Choose a spin style.
spin = Spinner(Spin1)
# Spin it now.
for i in range(50):
    print(u"\r{0}".format(spin.next()), end="")
    sys.stdout.flush()
    time.sleep(0.1)

Other styles in the below gif.

Styles of spin in py-spin package.

十六岁半 2024-10-24 03:40:38

获取出色的 progressbar 模块 - http://code.google.com /p/python-进度条/
使用旋转标记。

Grab the awesome progressbar module - http://code.google.com/p/python-progressbar/
use RotatingMarker.

一刻暧昧 2024-10-24 03:40:38

我构建了一个通用的单例,由整个应用程序共享

from itertools import cycle
import threading
import time


class Spinner:
    __default_spinner_symbols_list = ['|-----|', '|#----|', '|-#---|', '|--#--|', '|---#-|', '|----#|']

    def __init__(self, spinner_symbols_list: [str] = None):
        spinner_symbols_list = spinner_symbols_list if spinner_symbols_list else Spinner.__default_spinner_symbols_list
        self.__screen_lock = threading.Event()
        self.__spinner = cycle(spinner_symbols_list)
        self.__stop_event = False
        self.__thread = None

    def get_spin(self):
        return self.__spinner

    def start(self, spinner_message: str):
        self.__stop_event = False
        time.sleep(0.3)

        def run_spinner(message):
            while not self.__stop_event:
                print("\r{message} {spinner}".format(message=message, spinner=next(self.__spinner)), end="")
                time.sleep(0.3)

            self.__screen_lock.set()

        self.__thread = threading.Thread(target=run_spinner, args=(spinner_message,), daemon=True)
        self.__thread.start()

    def stop(self):
        self.__stop_event = True
        if self.__screen_lock.is_set():
            self.__screen_lock.wait()
            self.__screen_lock.clear()
            print("\r", end="")

        print("\r", end="")

if __name__ == '__main__':
    import time
    # Testing
    spinner = Spinner()
    spinner.start("Downloading")
    # Make actions
    time.sleep(5) # Simulate a process
    #
    spinner.stop()

I built a generic Singleton, shared by the entire application

from itertools import cycle
import threading
import time


class Spinner:
    __default_spinner_symbols_list = ['|-----|', '|#----|', '|-#---|', '|--#--|', '|---#-|', '|----#|']

    def __init__(self, spinner_symbols_list: [str] = None):
        spinner_symbols_list = spinner_symbols_list if spinner_symbols_list else Spinner.__default_spinner_symbols_list
        self.__screen_lock = threading.Event()
        self.__spinner = cycle(spinner_symbols_list)
        self.__stop_event = False
        self.__thread = None

    def get_spin(self):
        return self.__spinner

    def start(self, spinner_message: str):
        self.__stop_event = False
        time.sleep(0.3)

        def run_spinner(message):
            while not self.__stop_event:
                print("\r{message} {spinner}".format(message=message, spinner=next(self.__spinner)), end="")
                time.sleep(0.3)

            self.__screen_lock.set()

        self.__thread = threading.Thread(target=run_spinner, args=(spinner_message,), daemon=True)
        self.__thread.start()

    def stop(self):
        self.__stop_event = True
        if self.__screen_lock.is_set():
            self.__screen_lock.wait()
            self.__screen_lock.clear()
            print("\r", end="")

        print("\r", end="")

if __name__ == '__main__':
    import time
    # Testing
    spinner = Spinner()
    spinner.start("Downloading")
    # Make actions
    time.sleep(5) # Simulate a process
    #
    spinner.stop()
红墙和绿瓦 2024-10-24 03:40:38

您可以编写 '\r\033[K' 来清除当前行。以下是@nos 修改的示例。

import sys
import time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()

for _ in range(1, 10):
    content = f'\r{next(spinner)} Downloading...'
    print(content, end="")
    time.sleep(0.1)
    print('\r\033[K', end="")

对于任何对nodejs感兴趣的人,我还写了一个nodejs示例。

function* makeSpinner(start = 0, end = 100, step = 1) {
  let iterationCount = 0;
  while (true) {
    for (const char of '|/-\\') {
      yield char;
    }
  }
  return iterationCount;
}

async function sleep(seconds) {
  return new Promise((resolve) => {
    setTimeout(resolve, seconds * 1000);
  });
}

(async () => {
  const spinner = makeSpinner();
  for (let i = 0; i < 10; i++) {
    content = `\r${spinner.next().value} Downloading...`;
    process.stdout.write(content);
    await sleep(0.1);
    process.stdout.write('\r\033[K');
  }
})();

You can write '\r\033[K' to clear the current line. And the following is a example modified from @nos.

import sys
import time

def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor

spinner = spinning_cursor()

for _ in range(1, 10):
    content = f'\r{next(spinner)} Downloading...'
    print(content, end="")
    time.sleep(0.1)
    print('\r\033[K', end="")

For anyone who interested in nodejs, I also write a nodejs example.

function* makeSpinner(start = 0, end = 100, step = 1) {
  let iterationCount = 0;
  while (true) {
    for (const char of '|/-\\') {
      yield char;
    }
  }
  return iterationCount;
}

async function sleep(seconds) {
  return new Promise((resolve) => {
    setTimeout(resolve, seconds * 1000);
  });
}

(async () => {
  const spinner = makeSpinner();
  for (let i = 0; i < 10; i++) {
    content = `\r${spinner.next().value} Downloading...`;
    process.stdout.write(content);
    await sleep(0.1);
    process.stdout.write('\r\033[K');
  }
})();

云裳 2024-10-24 03:40:38

curses 模块。 我会看看 addstr() 和 addch( ) 函数。虽然从未使用过它。

curses module. i'd have a look at the addstr() and addch() functions. Never used it though.

花落人断肠 2024-10-24 03:40:38

对于更高级的控制台操作,在 unix 上,您可以使用 curses python 模块 ,在 Windows 上,您可以使用 WConio 它提供了与 curses 库等效的功能。

For more advanced console manipulations, on unix you can use the curses python module, and on windows, you can use WConio which provides equivalent functionality of the curses library.

泪痕残 2024-10-24 03:40:38
#!/usr/bin/env python

import sys

chars = '|/-\\'

for i in xrange(1,1000):
    for c in chars:
        sys.stdout.write(c)
        sys.stdout.write('\b')
        sys.stdout.flush()

注意事项:
根据我的经验,这并不适用于所有终端。在 Unix/Linux 下执行此操作的更强大方法是使用 curses 模块,该模块在 Windows 下不起作用。
您可能希望通过后台进行的实际处理来减慢速度。

#!/usr/bin/env python

import sys

chars = '|/-\\'

for i in xrange(1,1000):
    for c in chars:
        sys.stdout.write(c)
        sys.stdout.write('\b')
        sys.stdout.flush()

CAVEATS:
In my experience this doesn't work in all terminals. A more robust way to do this under Unix/Linux, be it more complicated is to use the curses module, which doesn't work under Windows.
You probably want to slow it down some how with actual processing that is going on in the background.

羅雙樹 2024-10-24 03:40:38

开始吧——简单明了。

import sys
import time

idx = 0
cursor = ['|','/','-','\\'] #frames of an animated cursor

while True:
    sys.stdout.write(cursor[idx])
    sys.stdout.write('\b')
    idx = idx + 1

    if idx > 3:
        idx = 0

    time.sleep(.1)

Here ya go - simple and clear.

import sys
import time

idx = 0
cursor = ['|','/','-','\\'] #frames of an animated cursor

while True:
    sys.stdout.write(cursor[idx])
    sys.stdout.write('\b')
    idx = idx + 1

    if idx > 3:
        idx = 0

    time.sleep(.1)
话少心凉 2024-10-24 03:40:38

粗略但简单的解决方案:

import sys
import time
cursor = ['|','/','-','\\']
for count in range(0,1000):
  sys.stdout.write('\b{}'.format(cursor[count%4]))
  sys.stdout.flush()
  # replace time.sleep() with some logic
  time.sleep(.1)

有明显的局限性,但同样是粗略的。

Crude but simple solution:

import sys
import time
cursor = ['|','/','-','\\']
for count in range(0,1000):
  sys.stdout.write('\b{}'.format(cursor[count%4]))
  sys.stdout.flush()
  # replace time.sleep() with some logic
  time.sleep(.1)

There are obvious limitations, but again, crude.

断爱 2024-10-24 03:40:38

我提出了一个使用装饰器的解决方案

from itertools import cycle
import functools
import threading
import time


def spinner(message, spinner_symbols: list = None):
    spinner_symbols = spinner_symbols or list("|/-\\")
    spinner_symbols = cycle(spinner_symbols)
    global spinner_event
    spinner_event = True

    def start():
        global spinner_event
        while spinner_event:
            symbol = next(spinner_symbols)
            print("\r{message} {symbol}".format(message=message, symbol=symbol), end="")
            time.sleep(0.3)

    def stop():
        global spinner_event
        spinner_event = False
        print("\r", end="")

    def external(fct):
        @functools.wraps(fct)
        def wrapper(*args):
            spinner_thread = threading.Thread(target=start, daemon=True)
            spinner_thread.start()
            result = fct(*args)
            stop()
            spinner_thread.join()

            return result

        return wrapper

    return external

简单用法

@spinner("Downloading")
def f():
    time.sleep(10)

I propose a solution using decorators

from itertools import cycle
import functools
import threading
import time


def spinner(message, spinner_symbols: list = None):
    spinner_symbols = spinner_symbols or list("|/-\\")
    spinner_symbols = cycle(spinner_symbols)
    global spinner_event
    spinner_event = True

    def start():
        global spinner_event
        while spinner_event:
            symbol = next(spinner_symbols)
            print("\r{message} {symbol}".format(message=message, symbol=symbol), end="")
            time.sleep(0.3)

    def stop():
        global spinner_event
        spinner_event = False
        print("\r", end="")

    def external(fct):
        @functools.wraps(fct)
        def wrapper(*args):
            spinner_thread = threading.Thread(target=start, daemon=True)
            spinner_thread.start()
            result = fct(*args)
            stop()
            spinner_thread.join()

            return result

        return wrapper

    return external

Simple usage

@spinner("Downloading")
def f():
    time.sleep(10)
洒一地阳光 2024-10-24 03:40:38
import sys
def DrowWaitCursor(counter):
    if counter % 4 == 0:
        print("/",end = "")
    elif counter % 4 == 1:
        print("-",end = "")
    elif counter % 4 == 2:
        print("\\",end = "")
    elif counter % 4 == 3:
        print("|",end = "")
    sys.stdout.flush()
    sys.stdout.write('\b') 

这也可以是使用带有参数的函数的另一种解决方案。

import sys
def DrowWaitCursor(counter):
    if counter % 4 == 0:
        print("/",end = "")
    elif counter % 4 == 1:
        print("-",end = "")
    elif counter % 4 == 2:
        print("\\",end = "")
    elif counter % 4 == 3:
        print("|",end = "")
    sys.stdout.flush()
    sys.stdout.write('\b') 

This can be also another solution using a function with a parameter.

没有心的人 2024-10-24 03:40:38

大约一周前,我刚刚开始使用 python,并发现了这篇文章。我将我在这里找到的一些内容与我在其他地方学到的有关线程和队列的内容结合起来,以提供我认为更好的实现。在我的解决方案中,写入屏幕是由检查队列内容的线程处理的。如果该队列有内容,游标旋转线程就会知道停止。另一方面,游标旋转线程使用队列作为锁,因此打印线程知道在旋转器代码的完整传递完成之前不要打印。这可以防止竞争条件和人们用来保持控制台干净的大量多余代码。

见下文:

import threading, queue, itertools, sys, time # all required for my version of spinner
import datetime #not required for spinning cursor solution, only my example

console_queue = queue.Queue() # this queue should be initialized before functions
screenlock = queue.Queue()    # this queue too...


def main():
    threading.Thread(target=spinner).start()
    threading.Thread(target=consoleprint).start()

    while True:
        # instead of invoking print or stdout.write, we just add items to the console_queue
        # The next three lines are an example of my code in practice.
        time.sleep(.5) # wait half a second
        currenttime = "[" + datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") + "] "
        console_queue.put(currenttime) # The most important part.  Substitute your print and stdout functions with this.


def spinner(console_queue = console_queue, screenlock = screenlock):
    spinnerlist = itertools.cycle(['|', '/', '-', '\\'])
    while True:
        if console_queue.empty():
            screenlock.put("locked")
            sys.stdout.write(next(spinnerlist)) 
            sys.stdout.flush()  
            sys.stdout.write('\b')
            sys.stdout.flush()   
            screenlock.get()
            time.sleep(.1)


def consoleprint(console_queue = console_queue, screenlock = screenlock):
    while True:
        if not console_queue.empty():
            while screenlock.empty() == False:
                time.sleep(.1)
            sys.stdout.flush()
            print(console_queue.get())
            sys.stdout.flush()


if __name__ == "__main__":
    main()

说了我所说的一切并写下了我所写的一切,我只做了一周的Python工作。如果有更干净的方法来做到这一点,或者我错过了一些我很想学习的最佳实践。谢谢。

I just started with python about a week ago and found this posting. I've combined a bit of what I found here with stuff I learned about threads and queues elsewhere to provide a much better implementation in my opinion. In my solution, writing to the screen is handled by a thread that checks a queue for content. If that queue has content, the cursor spinning thread knows to stop. On the flipside, the cursor spinning thread uses a queue as a lock so the printing thread knows not to print until a full pass of the spinner code is complete. This prevents race conditions and a lot of excess code people are using to keep the console clean.

See below:

import threading, queue, itertools, sys, time # all required for my version of spinner
import datetime #not required for spinning cursor solution, only my example

console_queue = queue.Queue() # this queue should be initialized before functions
screenlock = queue.Queue()    # this queue too...


def main():
    threading.Thread(target=spinner).start()
    threading.Thread(target=consoleprint).start()

    while True:
        # instead of invoking print or stdout.write, we just add items to the console_queue
        # The next three lines are an example of my code in practice.
        time.sleep(.5) # wait half a second
        currenttime = "[" + datetime.datetime.now().strftime("%d/%m/%Y %H:%M:%S") + "] "
        console_queue.put(currenttime) # The most important part.  Substitute your print and stdout functions with this.


def spinner(console_queue = console_queue, screenlock = screenlock):
    spinnerlist = itertools.cycle(['|', '/', '-', '\\'])
    while True:
        if console_queue.empty():
            screenlock.put("locked")
            sys.stdout.write(next(spinnerlist)) 
            sys.stdout.flush()  
            sys.stdout.write('\b')
            sys.stdout.flush()   
            screenlock.get()
            time.sleep(.1)


def consoleprint(console_queue = console_queue, screenlock = screenlock):
    while True:
        if not console_queue.empty():
            while screenlock.empty() == False:
                time.sleep(.1)
            sys.stdout.flush()
            print(console_queue.get())
            sys.stdout.flush()


if __name__ == "__main__":
    main()

Having said all I said and written all I've written, I've only been doing python stuff for a week. If there are cleaner ways of doing this or I missed some best practices I'd love to learn. Thanks.

想你只要分分秒秒 2024-10-24 03:40:38

超级简单的事情:
如果您知道最终指标,那么这也会打印进度和 eta。

from datetime import datetime
import itertools

def progress(title: str, total):
moon = itertools.cycle(["

Something super simple:
If you know the final metric then this will print the progress and eta as well.

from datetime import datetime
import itertools

def progress(title: str, total):
    moon = itertools.cycle(["????", "????", "????", "????", "????", "????", "????", "????"])
    start_time = datetime.now()

def show(current):
    curr_time = datetime.now()
    time_taken = curr_time - start_time
    print("  ", next(moon), title, current, "/", total,
          " progress: ", round((100.0 * current) / total, 2), "%",
          " eta: ", (time_taken * (total - current)) / current, end="\r ")

    return show
笑脸一如从前 2024-10-24 03:40:38

我们开始吧,更简单、更概念化:

import sys, time
pattern= ['-','/','|','\\'] # list for cursor graphics

for j in range(0, 101):
      for i in pattern:
          time.sleep(0.1)
          L = "     Loading... " + str(j) + "%" + str(i)
          sys.stdout.write(L+ "\r")

在文件中执行代码,否则它将无法工作(不要尝试在 Python 终端中执行代码)

输出:

Loading...65%/
  1. 调整 time.sleep () 用于加载时间。
  2. 调整不同图形的pattern列表。

示例:

pattern = ['❤', '

Here we go, much simplier and more conceptual:

import sys, time
pattern= ['-','/','|','\\'] # list for cursor graphics

for j in range(0, 101):
      for i in pattern:
          time.sleep(0.1)
          L = "     Loading... " + str(j) + "%" + str(i)
          sys.stdout.write(L+ "\r")

Execute your code within the file otherwise it won't work (don't try to execute code in Python terminal)

Output:

Loading...65%/
  1. Adjust time.sleep() for loading time.
  2. Adjust pattern list for different graphics.

Example:

pattern = ['❤', '????','????','????','????','????']

Output:

THE COLOR BLINGING HEART
Oooh! this can impress your lover ???????? Haha..!

In line 6: *L = " Loading... " + str(j) + "%" + str(i)

Here j is integer (number) 0 to 100, so for printing using sys.std.write() it is necessary to convert integer to string so we called str(j).

美煞众生 2024-10-24 03:40:38

alive-progress 库有很多选项。

您可以通过从终端运行以下命令来尝试实时演示:

python -m alive_progress.tools.demo

The alive-progress library has a lot of options.

You can try a live demo by running the following command from a terminal:

python -m alive_progress.tools.demo

花辞树 2024-10-24 03:40:38
import requests
import time
import sys

weathercity = input("What city are you in? ")
weather = requests.get('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')
url = ('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')




def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor


data = weather.json()

temp = data['main']['temp']
description = data['weather'][0]['description']
weatherprint ="In {}, it is currently {}°C with {}."
spinner = spinning_cursor()
for _ in range(25):
    sys.stdout.write(next(spinner))
    sys.stdout.flush()
    time.sleep(0.1)
    sys.stdout.write('\b')

convert = int(temp - 273.15)
print(weatherprint.format(weathercity, convert, description))
import requests
import time
import sys

weathercity = input("What city are you in? ")
weather = requests.get('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')
url = ('http://api.openweathermap.org/data/2.5/weather?q='+weathercity+'&appid=886705b4c1182eb1c69f28eb8c520e20')




def spinning_cursor():
    while True:
        for cursor in '|/-\\':
            yield cursor


data = weather.json()

temp = data['main']['temp']
description = data['weather'][0]['description']
weatherprint ="In {}, it is currently {}°C with {}."
spinner = spinning_cursor()
for _ in range(25):
    sys.stdout.write(next(spinner))
    sys.stdout.flush()
    time.sleep(0.1)
    sys.stdout.write('\b')

convert = int(temp - 273.15)
print(weatherprint.format(weathercity, convert, description))
最美不过初阳 2024-10-24 03:40:38

如果你想要 python 文本旋转器,你可以看图片

简单:

print_spinner("Hayatta en hakiki mürşit ilimdir.")

if you wanna python text spinner you can look picture

Simple:

print_spinner("Hayatta en hakiki mürşit ilimdir.")

眸中客 2024-10-24 03:40:38

这是最简单的 python 加载旋转器:

import  time           
spin=["loading...... ", "|", "/","-", "\"]   
for i in spin:
  print("\b"+i, end=" ") 
  time.sleep (0.2)               

输出:

loading...... |                       

Here is the simplest loading spinner for python:

import  time           
spin=["loading...... ", "|", "/","-", "\"]   
for i in spin:
  print("\b"+i, end=" ") 
  time.sleep (0.2)               

Output:

loading...... |                       
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文