I have many “can’t encode” and “can’t decode” problems with Python when I run my applications from the console. But in the EclipsePyDev IDE, the default character encoding is set to UTF-8, and I’m fine.
I searched around for setting the default encoding, and people say that Python deletes the sys.setdefaultencoding function on startup, and we can not use it.
Here is a simpler method (hack) that gives you back the setdefaultencoding() function that was deleted from sys:
import sys
# sys.setdefaultencoding() does not exist, here!
reload(sys) # Reload does the trick!
sys.setdefaultencoding('UTF8')
(Note for Python 3.4+: reload() is in the importlib library.)
This is not a safe thing to do, though: this is obviously a hack, since sys.setdefaultencoding() is purposely removed from sys when Python starts. Reenabling it and changing the default encoding can break code that relies on ASCII being the default (this code can be third-party, which would generally make fixing it impossible or dangerous).
回答 1
如果在尝试通过管道传输/重定向脚本输出时收到此错误
UnicodeEncodeError: 'ascii' codec can't encode characters in position 0-5: ordinal not in range(128)
Starting with PyDev 3.4.1, the default encoding is not being changed anymore.
See this ticket for details.
For earlier versions a solution is to make sure PyDev does not run with UTF-8 as the default encoding. Under Eclipse, run dialog settings (“run configurations”, if I remember correctly); you can choose the default encoding on the common tab. Change it to US-ASCII if you want to have these errors ‘early’ (in other words: in your PyDev environment). Also see an original blog post for this workaround.
回答 4
关于python2(仅限python2),一些以前的答案依赖于使用以下技巧:
import sys
reload(sys)# Reload is a hack
sys.setdefaultencoding('UTF8')
In my case, it come with a side-effect: I’m using ipython notebooks, and once I run the code the ´print´ function no longer works. I guess there would be solution to it, but still I think using the hack should not be the correct option.
After trying many options, the one that worked for me was using the same code in the sitecustomize.py, where that piece of code is meant to be. After evaluating that module, the setdefaultencoding function is removed from sys.
So the solution is to append to file /usr/lib/python2.7/sitecustomize.py the code:
import sys
sys.setdefaultencoding('UTF8')
When I use virtualenvwrapper the file I edit is ~/.virtualenvs/venv-name/lib/python2.7/sitecustomize.py.
And when I use with python notebooks and conda, it is ~/anaconda2/lib/python2.7/sitecustomize.py
In python 2 which was not as strongly typed regarding the encoding of strings you could perform operations on differently encoded strings, and succeed. E.g. the following would return True.
u'Toshio' == 'Toshio'
That would hold for every (normal, unprefixed) string that was encoded in sys.getdefaultencoding(), which defaulted to ascii, but not others.
The default encoding was meant to be changed system-wide in site.py, but not somewhere else. The hacks (also presented here) to set it in user modules were just that: hacks, not the solution.
Python 3 did changed the system encoding to default to utf-8 (when LC_CTYPE is unicode-aware), but the fundamental problem was solved with the requirement to explicitly encode “byte”strings whenever they are used with unicode strings.
First: reload(sys) and setting some random default encoding just regarding the need of an output terminal stream is bad practice. reload often changes things in sys which have been put in place depending on the environment – e.g. sys.stdin/stdout streams, sys.excepthook, etc.
Solving the encode problem on stdout
The best solution I know for solving the encode problem of print‘ing unicode strings and beyond-ascii str‘s (e.g. from literals) on sys.stdout is: to take care of a sys.stdout (file-like object) which is capable and optionally tolerant regarding the needs:
When sys.stdout.encoding is None for some reason, or non-existing, or erroneously false or “less” than what the stdout terminal or stream really is capable of, then try to provide a correct .encoding attribute. At last by replacing sys.stdout & sys.stderr by a translating file-like object.
When the terminal / stream still cannot encode all occurring unicode chars, and when you don’t want to break print‘s just because of that, you can introduce an encode-with-replace behavior in the translating file-like object.
Here an example:
#!/usr/bin/env python
# encoding: utf-8
import sys
class SmartStdout:
def __init__(self, encoding=None, org_stdout=None):
if org_stdout is None:
org_stdout = getattr(sys.stdout, 'org_stdout', sys.stdout)
self.org_stdout = org_stdout
self.encoding = encoding or \
getattr(org_stdout, 'encoding', None) or 'utf-8'
def write(self, s):
self.org_stdout.write(s.encode(self.encoding, 'backslashreplace'))
def __getattr__(self, name):
return getattr(self.org_stdout, name)
if __name__ == '__main__':
if sys.stdout.isatty():
sys.stdout = sys.stderr = SmartStdout()
us = u'aouäöüфżß²'
print us
sys.stdout.flush()
Using beyond-ascii plain string literals in Python 2 / 2 + 3 code
The only good reason to change the global default encoding (to UTF-8 only) I think is regarding an application source code decision – and not because of I/O stream encodings issues: For writing beyond-ascii string literals into code without being forced to always use u'string' style unicode escaping. This can be done rather consistently (despite what anonbadger‘s article says) by taking care of a Python 2 or Python 2 + 3 source code basis which uses ascii or UTF-8 plain string literals consistently – as far as those strings potentially undergo silent unicode conversion and move between modules or potentially go to stdout. For that, prefer “# encoding: utf-8” or ascii (no declaration). Change or drop libraries which still rely in a very dumb way fatally on ascii default encoding errors beyond chr #127 (which is rare today).
And do like this at application start (and/or via sitecustomize.py) in addition to the SmartStdout scheme above – without using reload(sys):
...
def set_defaultencoding_globally(encoding='utf-8'):
assert sys.getdefaultencoding() in ('ascii', 'mbcs', encoding)
import imp
_sys_org = imp.load_dynamic('_sys_org', 'sys')
_sys_org.setdefaultencoding(encoding)
if __name__ == '__main__':
sys.stdout = sys.stderr = SmartStdout()
set_defaultencoding_globally('utf-8')
s = 'aouäöüфżß²'
print s
This way string literals and most operations (except character iteration) work comfortable without thinking about unicode conversion as if there would be Python3 only.
File I/O of course always need special care regarding encodings – as it is in Python3.
Note: plains strings then are implicitely converted from utf-8 to unicode in SmartStdout before being converted to the output stream enconding.
Here is the approach I used to produce code that was compatible with both python2 and python3 and always produced utf8 output. I found this answer elsewhere, but I can’t remember the source.
This approach works by replacing sys.stdout with something that isn’t quite file-like (but still only using things in the standard library). This may well cause problems for your underlying libraries, but in the simple case where you have good control over how sys.stdout out is used through your framework this can be a reasonable approach.
# Encoding for file names
filesystemencoding = sys.getfilesystemencoding()
encoding ="ascii"if sys.platform =='win32':# On Windows, we could use "mbcs". However, to give the user# a portable encoding name, we need to find the code page try:# --> 6/5/17 hack to force IDLE to display utf-8 rather than cp1252# --> encoding = locale.getdefaultlocale()[1]
encoding ='utf-8'
codecs.lookup(encoding)exceptLookupError:pass
This is a quick hack for anyone who is (1) On a Windows platform (2) running Python 2.7 and (3) annoyed because a nice piece of software (i.e., not written by you so not immediately a candidate for encode/decode printing maneuvers) won’t display the “pretty unicode characters” in the IDLE environment (Pythonwin prints unicode fine), For example, the neat First Order Logic symbols that Stephan Boyer uses in the output from his pedagogic prover at First Order Logic Prover.
I didn’t like the idea of forcing a sys reload and I couldn’t get the system to cooperate with setting environment variables like PYTHONIOENCODING (tried direct Windows environment variable and also dropping that in a sitecustomize.py in site-packages as a one liner =’utf-8′).
So, if you are willing to hack your way to success, go to your IDLE directory, typically:
“C:\Python27\Lib\idlelib”
Locate the file IOBinding.py. Make a copy of that file and store it somewhere else so you can revert to original behavior when you choose. Open the file in the idlelib with an editor (e.g., IDLE). Go to this code area:
# Encoding for file names
filesystemencoding = sys.getfilesystemencoding()
encoding = "ascii"
if sys.platform == 'win32':
# On Windows, we could use "mbcs". However, to give the user
# a portable encoding name, we need to find the code page
try:
# --> 6/5/17 hack to force IDLE to display utf-8 rather than cp1252
# --> encoding = locale.getdefaultlocale()[1]
encoding = 'utf-8'
codecs.lookup(encoding)
except LookupError:
pass
In other words, comment out the original code line following the ‘try‘ that was making the encoding variable equal to locale.getdefaultlocale (because that will give you cp1252 which you don’t want) and instead brute force it to ‘utf-8’ (by adding the line ‘encoding = ‘utf-8‘ as shown).
I believe this only affects IDLE display to stdout and not the encoding used for file names etc. (that is obtained in the filesystemencoding prior). If you have a problem with any other code you run in IDLE later, just replace the IOBinding.py file with the original unmodified file.
Is there a way in python to programmatically determine the width of the console? I mean the number of characters that fits in one line without wrapping, not the pixel width of the window.
Edit
Looking for a solution that works on Linux
回答 0
import os
rows, columns = os.popen('stty size','r').read().split()
import os
rows, columns = os.popen('stty size', 'r').read().split()
uses the ‘stty size’ command which according to a thread on the python mailing list is reasonably universal on linux. It opens the ‘stty size’ command as a file, ‘reads’ from it, and uses a simple string split to separate the coordinates.
Unlike the os.environ[“COLUMNS”] value (which I can’t access in spite of using bash as my standard shell) the data will also be up-to-date whereas I believe the os.environ[“COLUMNS”] value would only be valid for the time of the launch of the python interpreter (suppose the user resized the window since then).
(See answer by @GringoSuave on how to do this on python 3.3+)
EDIT: oh, I’m sorry. That’s not a python standard lib one, here’s the source of console.py (I don’t know where it’s from).
The module seems to work like that: It checks if termcap is available, when yes. It uses that; if no it checks whether the terminal supports a special ioctl call and that does not work, too, it checks for the environment variables some shells export for that.
This will probably work on UNIX only.
def getTerminalSize():
import os
env = os.environ
def ioctl_GWINSZ(fd):
try:
import fcntl, termios, struct, os
cr = struct.unpack('hh', fcntl.ioctl(fd, termios.TIOCGWINSZ,
'1234'))
except:
return
return cr
cr = ioctl_GWINSZ(0) or ioctl_GWINSZ(1) or ioctl_GWINSZ(2)
if not cr:
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
cr = ioctl_GWINSZ(fd)
os.close(fd)
except:
pass
if not cr:
cr = (env.get('LINES', 25), env.get('COLUMNS', 80))
### Use get(key[, default]) instead of a try/catch
#try:
# cr = (env['LINES'], env['COLUMNS'])
#except:
# cr = (25, 80)
return int(cr[1]), int(cr[0])
import os
columns, rows = os.get_terminal_size(0)
# or
import shutil
columns, rows = shutil.get_terminal_size()
The shutil function is just a wrapper around os one that catches some errors and set up a fallback, however it has one huge caveat – it breaks when piping!, which is a pretty huge deal.
To get terminal size when piping use os.get_terminal_size(0) instead.
First argument 0 is an argument indicating that stdin file descriptor should be used instead of default stdout. We want to use stdin because stdout detaches itself when it is being piped which in this case raises an error.
I’ve tried to figure out when would it makes sense to use stdout instead of stdin argument and have no idea why it’s a default here.
It looks like there are some problems with that code, Johannes:
getTerminalSize needs to import os
what is env? looks like os.environ.
Also, why switch lines and cols before returning? If TIOCGWINSZ and stty both say lines then cols, I say leave it that way. This confused me for a good 10 minutes before I noticed the inconsistency.
Sridhar, I didn’t get that error when I piped output. I’m pretty sure it’s being caught properly in the try-except.
pascal, "HHHH" doesn’t work on my machine, but "hh" does. I had trouble finding documentation for that function. It looks like it’s platform dependent.
chochem, incorporated.
Here’s my version:
def getTerminalSize():
"""
returns (lines:int, cols:int)
"""
import os, struct
def ioctl_GWINSZ(fd):
import fcntl, termios
return struct.unpack("hh", fcntl.ioctl(fd, termios.TIOCGWINSZ, "1234"))
# try stdin, stdout, stderr
for fd in (0, 1, 2):
try:
return ioctl_GWINSZ(fd)
except:
pass
# try os.ctermid()
try:
fd = os.open(os.ctermid(), os.O_RDONLY)
try:
return ioctl_GWINSZ(fd)
finally:
os.close(fd)
except:
pass
# try `stty size`
try:
return tuple(int(x) for x in os.popen("stty size", "r").read().split())
except:
pass
# try environment variables
try:
return tuple(int(os.getenv(var)) for var in ("LINES", "COLUMNS"))
except:
pass
# i give up. return default.
return (25, 80)
Many of the Python 2 implementations here will fail if there is no controlling terminal when you call this script. You can check sys.stdout.isatty() to determine if this is in fact a terminal, but that will exclude a bunch of cases, so I believe the most pythonic way to figure out the terminal size is to use the builtin curses package.
import curses
w = curses.initscr()
height, width = w.getmaxyx()
However this failed for me because I was working on a script that expects redirected input on stdin, and stty would complain that “stdin isn’t a terminal” in that case.
I was able to make it work like this:
with open('/dev/tty') as tty:
height, width = subprocess.check_output(['stty', 'size'], stdin=tty).split()
@reannual’s answer works well, but there’s an issue with it: os.popenis now deprecated. The subprocess module should be used instead, so here’s a version of @reannual’s code that uses subprocess and directly answers the question (by giving the column width directly as an int:
I was looking for the very same thing. It is very easy to use and offers tools for coloring, styling and positioning in the terminal. What you need is as easy as:
from blessings import Terminal
t = Terminal()
w = t.width
h = t.height
Works like a charm in Linux. (I’m not sure about MacOSX and Windows)
If you’re using Python 3.3 or above, I’d recommend the built-in get_terminal_size() as already recommended. However if you are stuck with an older version and want a simple, cross-platform way of doing this, you could use asciimatics. This package supports versions of Python back to 2.7 and uses similar options to those suggested above to get the current terminal/console size.
Simply construct your Screen class and use the dimensions property to get the height and width. This has been proven to work on Linux, OSX and Windows.
Oh – and full disclosure here: I am the author, so please feel free to open a new issue if you have any problems getting this to work.
def termsize():
导入shlex,子流程,重新
输出= subprocess.check_output(shlex.split('/ bin / stty -a'))
m = re.search('rows \ D +(?P \ d +); column \ D +(?P \ d +);',输出)
如果m:
返回m.group('rows'),m.group('columns')
引发OSError('错误响应:%s'%(输出))
Like most Python developers, I typically keep a console window open with the Python interpreter running to test commands, dir() stuff, help() stuff, etc.
Like any console, after a while the visible backlog of past commands and prints gets to be cluttered, and sometimes confusing when re-running the same command several times. I’m wondering if, and how, to clear the Python interpreter console.
I’ve heard about doing a system call and either calling cls on Windows or clear on Linux, but I was hoping there was something I could command the interpreter itself to do.
Note: I’m running on Windows, so Ctrl+L doesn’t work.
Although this is an older question, I thought I’d contribute something summing up what I think were the best of the other answers and add a wrinkle of my own by suggesting that you put these command(s) into a file and set your PYTHONSTARTUP environment variable to point to it. Since I’m on Windows at the moment, it’s slightly biased that way, but could easily be slanted some other direction.
my way of doing this is to write a function like so:
import os
import subprocess
def clear():
if os.name in ('nt','dos'):
subprocess.call("cls")
elif os.name in ('linux','osx','posix'):
subprocess.call("clear")
else:
print("\n") * 120
then call clear() to clear the screen.
this works on windows, osx, linux, bsd… all OSes.
回答 7
这是一个跨平台(Windows / Linux / Mac /可能还可以在if检查中添加的跨平台)版本代码,我结合了在此问题中找到的信息制作而成:
import os
clear =lambda: os.system('cls'if os.name=='nt'else'clear')
clear()
Here’s a cross platform (Windows / Linux / Mac / Probably others that you can add in the if check) version snippet I made combining information found in this question:
import os
clear = lambda: os.system('cls' if os.name=='nt' else 'clear')
clear()
class clear:def __call__(self):import os
if os.name==('ce','nt','dos'): os.system('cls')elif os.name=='posix': os.system('clear')else:print('\n'*120)def __neg__(self): self()def __repr__(self):
self();return''
clear=clear()
In my opinion calling cls with os is a bad idea generally. Imagine if I manage to change the cls or clear command on your system, and you run your script as admin or root.
class exxxit():"""Shortcut for exit() function, use 'x' now"""
quit_now = exit # original objectdef __repr__(self):
self.quit_now()# call original
x = exxxit()
Py2.7.1>help(x)Help on instance of exxxit in module __main__:class exxxit
|Shortcutfor exit() function, use 'x' now
||Methods defined here:|| __repr__(self)||----------------------------------------------------------------------|Dataand other attributes defined here:|| quit_now =Use exit()orCtrl-Z plus Return to exit
(stick this in .pythonstartup)
# My ctrl-l already kind of worked, but this might help someone else
# leaves prompt at bottom of the window though…
import readline
readline.parse_and_bind(‘\C-l: clear-screen’)
# This works in BASH because I have it in .inputrc as well, but for some
# reason it gets dropped when I go into Python
readline.parse_and_bind(‘\C-y: kill-whole-line’)
I couldn’t stand typing ‘exit()’ anymore and was delighted with martineau’s/Triptych’s tricks:
I slightly doctored it though (stuck it in .pythonstartup)
class exxxit():
"""Shortcut for exit() function, use 'x' now"""
quit_now = exit # original object
def __repr__(self):
self.quit_now() # call original
x = exxxit()
Py2.7.1>help(x)
Help on instance of exxxit in module __main__:
class exxxit
| Shortcut for exit() function, use 'x' now
|
| Methods defined here:
|
| __repr__(self)
|
| ----------------------------------------------------------------------
| Data and other attributes defined here:
|
| quit_now = Use exit() or Ctrl-Z plus Return to exit
The OS command clear in Linux and cls in Windows outputs a “magic string” which you can just print. To get the string, execute the command with popen and save it in a variable for later use:
from os import popen
with popen('clear') as f:
clear = f.read()
print clear
On my machine the string is '\x1b[H\x1b[2J'.
回答 17
这是两种不错的方法:
1。
import os
# Clear Windows command prompt.if(os.name in('ce','nt','dos')):
os.system('cls')# Clear the Linux terminal.elif('posix'in os.name):
os.system('clear')
import os
# Clear Windows command prompt.
if (os.name in ('ce', 'nt', 'dos')):
os.system('cls')
# Clear the Linux terminal.
elif ('posix' in os.name):
os.system('clear')
2.
import os
def clear():
if os.name == 'posix':
os.system('clear')
elif os.name in ('ce', 'nt', 'dos'):
os.system('cls')
clear()
This should be cross platform, and also uses the preferred subprocess.call instead of os.system as per the os.system docs. Should work in Python >= 2.4.
import subprocess
import os
if os.name == 'nt':
def clearscreen():
subprocess.call("cls", shell=True)
return
else:
def clearscreen():
subprocess.call("clear", shell=True)
return
I’m new to python (really really new) and in one of the books I’m reading to get acquainted with the language they teach how to create this little function to clear the console of the visible backlog and past commands and prints:
Open shell / Create new document / Create function as follows:
def clear():
print('\n' * 50)
Save it inside the lib folder in you python directory (mine is C:\Python33\Lib)
Next time you nedd to clear your console just call the function with:
clear()
that’s it.
PS: you can name you function anyway you want. Iv’ seen people using “wiper” “wipe” and variations.
Arch Linux (tested in xfce4-terminal with Python 3):
# Clear or wipe console (terminal):
# Use: clear() or wipe()
import os
def clear():
os.system('clear')
def wipe():
os.system("clear && printf '\e[3J'")
… added to ~/.pythonrc
clear() clears screen
wipe() wipes entire terminal buffer
回答 28
编辑:我刚刚读过“ Windows”,这是给Linux用户的,抱歉。
在bash中:
#!/bin/bashwhile["0"=="0"];do
clear
$@
while["$input"==""];do
read -p "Do you want to quit? (y/n): "-n 1-e input
if["$input"=="y"]; then
exit 1elif["$input"=="n"]; then
echo "Ok, keep working ;)"
fi
done
input=""
done
EDIT: I’ve just read “windows”, this is for linux users, sorry.
In bash:
#!/bin/bash
while [ "0" == "0" ]; do
clear
$@
while [ "$input" == "" ]; do
read -p "Do you want to quit? (y/n): " -n 1 -e input
if [ "$input" == "y" ]; then
exit 1
elif [ "$input" == "n" ]; then
echo "Ok, keep working ;)"
fi
done
input=""
done
Save it as “whatyouwant.sh”, chmod +x it then run:
./whatyouwant.sh python
or something other than python (idle, whatever).
This will ask you if you actually want to exit, if not it rerun python (or the command you gave as parameter).
This will clear all, the screen and all the variables/object/anything you created/imported in python.
OK, so this is a much less technical answer, but I’m using the Python plugin for Notepad++ and it turns out you can just clear the console manually by right-clicking on it and clicking “clear”. Hope this helps someone out there!
I wrote a simple console app to upload and download files from an FTP server using the ftplib.
I would like the app to show some visualization of its download/upload progress for the user; each time a data chunk is downloaded, I would like it to provide a progress update, even if it’s just a numeric representation like a percentage.
Importantly, I want to avoid erasing all the text that’s been printed to the console in previous lines (i.e. I don’t want to “clear” the entire terminal while printing the updated progress).
This seems a fairly common task – how can I go about making a progress bar or similar visualization that outputs to my console while preserving prior program output?
回答 0
一个简单的,可定制的进度条
以下是我经常使用的许多答案的汇总(不需要导入)。
# Print iterations progressdef printProgressBar (iteration, total, prefix ='', suffix ='', decimals =1, length =100, fill ='█', printEnd ="\r"):"""
Call in a loop to create terminal progress bar
@params:
iteration - Required : current iteration (Int)
total - Required : total iterations (Int)
prefix - Optional : prefix string (Str)
suffix - Optional : suffix string (Str)
decimals - Optional : positive number of decimals in percent complete (Int)
length - Optional : character length of bar (Int)
fill - Optional : bar fill character (Str)
printEnd - Optional : end character (e.g. "\r", "\r\n") (Str)
"""
percent =("{0:."+ str(decimals)+"f}").format(100*(iteration / float(total)))
filledLength = int(length * iteration // total)
bar = fill * filledLength +'-'*(length - filledLength)print('\r%s |%s| %s%% %s'%(prefix, bar, percent, suffix), end = printEnd)# Print New Line on Completeif iteration == total:print()
注意:这是针对Python 3的;有关在Python 2中使用此功能的详细信息,请参见注释。
样品用量
import time
# A List of Items
items = list(range(0,57))
l = len(items)# Initial call to print 0% progress
printProgressBar(0, l, prefix ='Progress:', suffix ='Complete', length =50)for i, item in enumerate(items):# Do stuff...
time.sleep(0.1)# Update Progress Bar
printProgressBar(i +1, l, prefix ='Progress:', suffix ='Complete', length =50)
There was discussion in the comments regarding an option that allows the progress bar to adjust dynamically to the terminal window width. While I don’t recommend this, here’s a gist that implements this feature (and notes the caveats).
回答 1
写入“ \ r”会将光标移回该行的开头。
这将显示一个百分比计数器:
import time
import sys
for i in range(100):
time.sleep(1)
sys.stdout.write("\r%d%%"% i)
sys.stdout.flush()
>>>import time
>>>from tqdm import tqdm
>>>for i in tqdm(range(100)):... time.sleep(1)...|###-------|35/10035%[elapsed:00:35 left:01:05,1.00 iters/sec]
>>> import time
>>> from tqdm import tqdm
>>> for i in tqdm(range(100)):
... time.sleep(1)
...
|###-------| 35/100 35% [elapsed: 00:35 left: 01:05, 1.00 iters/sec]
import click, sys
with click.progressbar(range(100000), file=sys.stderr, show_pos=True, width=70, bar_template='(_(_)=%(bar)sD(_(_| %(info)s', fill_char='=', empty_char=' ') as bar:
for i in bar:
pass
I realize I’m late to the game, but here’s a slightly Yum-style (Red Hat) one I wrote (not going for 100% accuracy here, but if you’re using a progress bar for that level of accuracy, then you’re WRONG anyway):
from time import sleep
from random import random
from clint.textui import progress
if __name__ =='__main__':for i in progress.bar(range(100)):
sleep(random()*0.2)for i in progress.dots(range(100)):
sleep(random()*0.2)
it has a lot of features including a progress bar:
from time import sleep
from random import random
from clint.textui import progress
if __name__ == '__main__':
for i in progress.bar(range(100)):
sleep(random() * 0.2)
for i in progress.dots(range(100)):
sleep(random() * 0.2)
this link provides a quick overview of its features
I am using progress from reddit. I like it because it can print progress for every item in one line, and it shouldn’t erase printouts from the program.
Edit: fixed link
回答 15
尝试安装此软件包 pip install progressbar2:
import time
import progressbar
for i in progressbar.progressbar(range(100)):
time.sleep(0.02)
import time, sys
# update_progress() : Displays or updates a console progress bar## Accepts a float between 0 and 1. Any int will be converted to a float.## A value under 0 represents a 'halt'.## A value at 1 or bigger represents 100%def update_progress(progress):
barLength =10# Modify this to change the length of the progress bar
status =""if isinstance(progress, int):
progress = float(progress)ifnot isinstance(progress, float):
progress =0
status ="error: progress var must be float\r\n"if progress <0:
progress =0
status ="Halt...\r\n"if progress >=1:
progress =1
status ="Done...\r\n"
block = int(round(barLength*progress))
text ="\rPercent: [{0}] {1}% {2}".format("#"*block +"-"*(barLength-block), progress*100, status)
sys.stdout.write(text)
sys.stdout.flush()
based on the above answers and other similar questions about CLI progress bar, I think I got a general common answer to all of them. Check it at https://stackoverflow.com/a/15860757/2254146
In summary, the code is this:
import time, sys
# update_progress() : Displays or updates a console progress bar
## Accepts a float between 0 and 1. Any int will be converted to a float.
## A value under 0 represents a 'halt'.
## A value at 1 or bigger represents 100%
def update_progress(progress):
barLength = 10 # Modify this to change the length of the progress bar
status = ""
if isinstance(progress, int):
progress = float(progress)
if not isinstance(progress, float):
progress = 0
status = "error: progress var must be float\r\n"
if progress < 0:
progress = 0
status = "Halt...\r\n"
if progress >= 1:
progress = 1
status = "Done...\r\n"
block = int(round(barLength*progress))
text = "\rPercent: [{0}] {1}% {2}".format( "#"*block + "-"*(barLength-block), progress*100, status)
sys.stdout.write(text)
sys.stdout.flush()
import urllib
from tqdm import tqdm
def my_hook(t):"""
Wraps tqdm instance. Don't forget to close() or __exit__()
the tqdm instance once you're done with it (easiest using `with` syntax).
Example
-------
>>> with tqdm(...) as t:
... reporthook = my_hook(t)
... urllib.urlretrieve(..., reporthook=reporthook)
"""
last_b =[0]def inner(b=1, bsize=1, tsize=None):"""
b : int, optional
Number of blocks just transferred [default: 1].
bsize : int, optional
Size of each block (in tqdm units) [default: 1].
tsize : int, optional
Total size (in tqdm units). If [default: None] remains unchanged.
"""if tsize isnotNone:
t.total = tsize
t.update((b - last_b[0])* bsize)
last_b[0]= b
return inner
eg_link ='http://www.doc.ic.ac.uk/~cod11/matryoshka.zip'with tqdm(unit='B', unit_scale=True, miniters=1,
desc=eg_link.split('/')[-1])as t:# all optional kwargs
urllib.urlretrieve(eg_link, filename='/dev/null',
reporthook=my_hook(t), data=None)
I recommend using tqdm – https://pypi.python.org/pypi/tqdm – which makes it simple to turn any iterable or process into a progress bar, and handles all messing about with terminals needed.
From the documentation: “tqdm can easily support callbacks/hooks and manual updates. Here’s an example with urllib”
import urllib
from tqdm import tqdm
def my_hook(t):
"""
Wraps tqdm instance. Don't forget to close() or __exit__()
the tqdm instance once you're done with it (easiest using `with` syntax).
Example
-------
>>> with tqdm(...) as t:
... reporthook = my_hook(t)
... urllib.urlretrieve(..., reporthook=reporthook)
"""
last_b = [0]
def inner(b=1, bsize=1, tsize=None):
"""
b : int, optional
Number of blocks just transferred [default: 1].
bsize : int, optional
Size of each block (in tqdm units) [default: 1].
tsize : int, optional
Total size (in tqdm units). If [default: None] remains unchanged.
"""
if tsize is not None:
t.total = tsize
t.update((b - last_b[0]) * bsize)
last_b[0] = b
return inner
eg_link = 'http://www.doc.ic.ac.uk/~cod11/matryoshka.zip'
with tqdm(unit='B', unit_scale=True, miniters=1,
desc=eg_link.split('/')[-1]) as t: # all optional kwargs
urllib.urlretrieve(eg_link, filename='/dev/null',
reporthook=my_hook(t), data=None)
回答 18
一个非常简单的解决方案是将以下代码放入循环中:
将其放在文件的正文(即顶部)中:
import sys
把它放在循环体中:
sys.stdout.write("-")# prints a dash for each iteration of loop
sys.stdout.flush()# ensures bar is displayed incrementally
import os
import time
def load(left_side, right_side, length, time):
x =0
y =""print"\r"while x < length:
space = length - len(y)
space =" "* space
z = left + y + space + right
print"\r", z,
y +="█"
time.sleep(time)
x +=1
cls()
lol i just wrote a whole thingy for this
heres the code keep in mind you cant use unicode when doing block ascii i use cp437
import os
import time
def load(left_side, right_side, length, time):
x = 0
y = ""
print "\r"
while x < length:
space = length - len(y)
space = " " * space
z = left + y + space + right
print "\r", z,
y += "█"
time.sleep(time)
x += 1
cls()
2.The square bracket ‘]’ and the percent number on the right side shift right as the ‘###’ get longer.
3. An error will occur if the expression ‘progress / 10’ can not return an integer.
And the following code will fix the problem above.
import sys
import time
max_length =5
at_length = max_length
empty ="-"
used ="%"
bar = empty * max_length
for i in range(0, max_length):
at_length -=1#setting empty and full spots
bar = used * i
bar = bar+empty * at_length
#\r is carriage return(sets cursor position in terminal to start of line)#\0 character escape
sys.stdout.write("[{}]\0\r".format(bar))
sys.stdout.flush()#do your stuff here instead of time.sleep
time.sleep(1)
sys.stdout.write("\n")
sys.stdout.flush()
import sys
import time
max_length = 5
at_length = max_length
empty = "-"
used = "%"
bar = empty * max_length
for i in range(0, max_length):
at_length -= 1
#setting empty and full spots
bar = used * i
bar = bar+empty * at_length
#\r is carriage return(sets cursor position in terminal to start of line)
#\0 character escape
sys.stdout.write("[{}]\0\r".format(bar))
sys.stdout.flush()
#do your stuff here instead of time.sleep
time.sleep(1)
sys.stdout.write("\n")
sys.stdout.flush()
回答 23
我写了一个简单的进度栏:
def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""):if len(border)!=2:print("parameter 'border' must include exactly 2 symbols!")returnNoneprint(prefix + border[0]+(filler * int(current / total * length)+(space *(length - int(current / total * length))))+ border[1], suffix,"\r", end="")if total == current:if oncomp:print(prefix + border[0]+ space * int(((length - len(oncomp))/2))+
oncomp + space * int(((length - len(oncomp))/2))+ border[1], suffix)ifnot oncomp:print(prefix + border[0]+(filler * int(current / total * length)+(space *(length - int(current / total * length))))+ border[1], suffix)
from time import sleep, time
start_time = time()for i in range(10):
pref = str((i+1)*10)+"% "
complete_text ="done in %s sec"% str(round(time()- start_time))
sleep(1)
bar(10, i +1, length=20, prefix=pref, oncomp=complete_text)
def bar(total, current, length=10, prefix="", filler="#", space=" ", oncomp="", border="[]", suffix=""):
if len(border) != 2:
print("parameter 'border' must include exactly 2 symbols!")
return None
print(prefix + border[0] + (filler * int(current / total * length) +
(space * (length - int(current / total * length)))) + border[1], suffix, "\r", end="")
if total == current:
if oncomp:
print(prefix + border[0] + space * int(((length - len(oncomp)) / 2)) +
oncomp + space * int(((length - len(oncomp)) / 2)) + border[1], suffix)
if not oncomp:
print(prefix + border[0] + (filler * int(current / total * length) +
(space * (length - int(current / total * length)))) + border[1], suffix)
as you can see, it have: length of bar, prefix and suffix, filler, space, text in bar on 100%(oncomp) and borders
here an example:
from time import sleep, time
start_time = time()
for i in range(10):
pref = str((i+1) * 10) + "% "
complete_text = "done in %s sec" % str(round(time() - start_time))
sleep(1)
bar(10, i + 1, length=20, prefix=pref, oncomp=complete_text)
20 character bar (1 character for every 5 (number wise))
Custom fill characters
Custom empty characters
Halt (any number below 0)
Done (100 and any number above 100)
Progress count (0-100 (below and above used for special functions))
Percentage number next to bar, and it’s a single line
Cons:
Supports integers only (It can be modified to support them though, by making the division an integer division, so just change prog2 = prog/5 to prog2 = int(prog/5))
回答 27
这是我的Python 3解决方案:
import time
for i in range(100):
time.sleep(1)
s ="{}% Complete".format(i)print(s,end=len(s)*'\b')
classtqdm():
""" Decorate an iterable object, returning an iterator which acts exactly like the original iterable, but prints a dynamically updating progressbar every time a value is requested. """def__init__(self, iterable=None, desc=None, total=None, leave=True,
file=None, ncols=None, mininterval=0.1,
maxinterval=10.0, miniters=None, ascii=None, disable=False,
unit='it', unit_scale=False, dynamic_ncols=False,
smoothing=0.3, bar_format=None, initial=0, position=None,
postfix=None, unit_divisor=1000):
classtqdm():
defupdate(self, n=1):
""" Manually update the progress bar, useful for streams such as reading files. E.g.: >>> t = tqdm(total=filesize) # Initialise >>> for current_buffer in stream: ... ... ... t.update(len(current_buffer)) >>> t.close() The last line is highly recommended, but possibly not necessary if ``t.update()`` will be called in such a way that ``filesize`` will be exactly reached and printed. Parameters ---------- n : int or float, optional Increment to add to the internal counter of iterations [default: 1]. If using float, consider specifying ``{n:.3f}`` or similar in ``bar_format``, or specifying ``unit_scale``. Returns ------- out : bool or None True if a ``display()`` was triggered. """defclose(self):
"""Cleanup and (if leave=False) close the progressbar."""defclear(self, nomove=False):
"""Clear current bar display."""defrefresh(self):
""" Force refresh the display of this bar. Parameters ---------- nolock : bool, optional If ``True``, does not lock. If [default: ``False``]: calls ``acquire()`` on internal lock. lock_args : tuple, optional Passed to internal lock's ``acquire()``. If specified, will only ``display()`` if ``acquire()`` returns ``True``. """defunpause(self):
"""Restart tqdm timer from last print time."""defreset(self, total=None):
""" Resets to 0 iterations for repeated use. Consider combining with ``leave=True``. Parameters ---------- total : int or float, optional. Total to use for the new bar. """defset_description(self, desc=None, refresh=True):
""" Set/modify description of the progress bar. Parameters ---------- desc : str, optional refresh : bool, optional Forces refresh [default: True]. """defset_postfix(self, ordered_dict=None, refresh=True, **tqdm_kwargs):
""" Set/modify postfix (additional stats) with automatic formatting based on datatype. Parameters ---------- ordered_dict : dict or OrderedDict, optional refresh : bool, optional Forces refresh [default: True]. kwargs : dict, optional """@classmethoddefwrite(cls, s, file=sys.stdout, end="\n"):
"""Print a message via tqdm (without overlap with bars)."""@propertydefformat_dict(self):
"""Public API for read-only member access."""defdisplay(self, msg=None, pos=None):
""" Use ``self.sp`` to display ``msg`` in the specified ``pos``. Consider overloading this function when inheriting to use e.g.: ``self.some_frontend(**self.format_dict)`` instead of ``self.sp``. Parameters ---------- msg : str, optional. What to display (default: ``repr(self)``). pos : int, optional. Position to ``moveto`` (default: ``abs(self.pos)``). """@classmethod@contextmanagerdefwrapattr(cls, stream, method, total=None, bytes=True, **tqdm_kwargs):
""" stream : file-like object. method : str, "read" or "write". The result of ``read()`` and the first argument of ``write()`` should have a ``len()``. >>> with tqdm.wrapattr(file_obj, "read", total=file_obj.size) as fobj: ... while True: ... chunk = fobj.read(chunk_size) ... if not chunk: ... break """@classmethoddefpandas(cls, *targs, **tqdm_kwargs):
"""Registers the current `tqdm` class with `pandas`."""deftrange(*args, **tqdm_kwargs):
""" A shortcut for `tqdm(xrange(*args), **tqdm_kwargs)`. On Python3+, `range` is used instead of `xrange`. """
fromtqdmimporttqdm, trangefromrandomimportrandom, randintfromtimeimportsleepwithtrange(10) ast:
foriint:
# Description will be displayed on the leftt.set_description('GEN %i'%i)
# Postfix will be displayed on the right,# formatted automatically based on argument's datatypet.set_postfix(loss=random(), gen=randint(1,999), str='h',
lst=[1, 2])
sleep(0.1)
withtqdm(total=10, bar_format="{postfix[0]} {postfix[1][value]:>8.2g}",
postfix=["Batch", dict(value=0)]) ast:
foriinrange(10):
sleep(0.1)
t.postfix[1]["value"] =i/2t.update()
importpandasaspdimportnumpyasnpfromtqdmimporttqdmdf=pd.DataFrame(np.random.randint(0, 100, (100000, 6)))
# Register `pandas.progress_apply` and `pandas.Series.map_apply` with `tqdm`# (can use `tqdm.gui.tqdm`, `tqdm.notebook.tqdm`, optional kwargs, etc.)tqdm.pandas(desc="my bar!")
# Now you can use `progress_apply` instead of `apply`# and `progress_map` instead of `map`df.progress_apply(lambdax: x**2)
# can also groupby:# df.groupby(0).progress_apply(lambda x: x**2)
fromtqdm.daskimportTqdmCallbackwithTqdmCallback(desc="compute"):
...
arr.compute()
# or use callback globallycb=TqdmCallback(desc="global")
cb.register()
arr.compute()
# different celliterable=range(100)
pbar.reset(total=len(iterable)) # initialise with new `total`foriiniterable:
pbar.update()
pbar.refresh() # force print final status but don't `close()`
fromtqdmimporttqdmimportos.pathdeffind_files_recursively(path, show_progress=True):
files= []
# total=1 assumes `path` is a filet=tqdm(total=1, unit="file", disable=notshow_progress)
ifnotos.path.exists(path):
raiseIOError("Cannot find:"+path)
defappend_found_file(f):
files.append(f)
t.update()
deflist_found_dir(path):
"""returns os.listdir(path) assuming os.path.isdir(path)"""listing=os.listdir(path)
# subtract 1 since a "file" we found was actually this directoryt.total+=len(listing) -1# fancy way to give info without forcing a refresht.set_postfix(dir=path[-10:], refresh=False)
t.update(0) # may trigger a refreshreturnlistingdefrecursively_search(path):
ifos.path.isdir(path):
forfinlist_found_dir(path):
recursively_search(os.path.join(path, f))
else:
append_found_file(path)
recursively_search(path)
t.set_postfix(dir=path)
t.close()
returnfiles
fromtqdm.autoimporttqdm, trangefromtimeimportsleepbar=trange(10)
foriinbar:
# Print using tqdm class method .write()sleep(0.1)
ifnot (i%3):
tqdm.write("Done task %i"%i)
# Can also use bar.write()