I read this somewhere a while ago but cant seem to find it. I am trying to find a command that will execute commands in the terminal and then output the result.
For example: the script will be:
command 'ls -l'
It will out the result of running that command in the terminal
回答 0
做这件事有很多种方法:
一种简单的方法是使用os模块:
import os
os.system("ls -l")
子流程模块可以实现更复杂的事情:例如:
import subprocess
test = subprocess.Popen(["ping","-W","2","-c","1","192.168.1.70"], stdout=subprocess.PIPE)
output = test.communicate()[0]
You should also look into commands.getstatusoutput
This returns a tuple of length 2..
The first is the return integer ( 0 – when the commands is successful )
second is the whole output as will be shown in the terminal.
A package manager (like apt-get or brew) just gives your system an easy and automated way to install packages or libraries. Different systems use different programs. apt and its derivatives are used on Debian based linux systems. Red Hat-ish Linux systems use rpm (or at least they did many, many, years ago). yum is also a package manager for RedHat based systems.
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'%(输出))
import sys
for line in sys.stdin:# Decode what you receive:
line = line.decode('iso8859-1')# Work with Unicode internally:
line = line.upper()# Encode what you send:
line = line.encode('utf-8')
sys.stdout.write(line)
Your code works when run in an script because Python encodes the output to whatever encoding your terminal application is using. If you are piping you must encode it yourself.
A rule of thumb is: Always use Unicode internally. Decode what you receive, and encode what you send.
Another didactic example is a Python program to convert between ISO-8859-1 and UTF-8, making everything uppercase in between.
import sys
for line in sys.stdin:
# Decode what you receive:
line = line.decode('iso8859-1')
# Work with Unicode internally:
line = line.upper()
# Encode what you send:
line = line.encode('utf-8')
sys.stdout.write(line)
Setting the system default encoding is a bad idea, because some modules and libraries you use can rely on the fact it is ASCII. Don’t do it.
It’s not practical to explicitly print with a given encoding every time. That would be repetitive and error-prone.
A better solution is to change sys.stdout at the start of your program, to encode with a selected encoding. Here is one solution I found on Python: How is sys.stdout.encoding chosen?, in particular a comment by “toka”:
if __name__ =='__main__':if(sys.stdout.encoding isNone):print>> sys.stderr,"please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
what we can do is verify if isn’t setting and tell the user to set it before call script with :
if __name__ == '__main__':
if (sys.stdout.encoding is None):
print >> sys.stderr, "please set python env PYTHONIOENCODING=UTF-8, example: export PYTHONIOENCODING=UTF-8, when write to stdout."
exit(1)
Update to reply to the comment:
the problem just exist when piping to stdout .
I tested in Fedora 25 Python 2.7.13
Starting from PyCharm menu bar: File -> Settings… -> Editor -> File Encodings, then set: “IDE Encoding”, “Project Encoding” and “Default encoding for properties files” ALL to UTF-8 and she now works like a charm.
def __fix_io_encoding(last_resort_default='UTF-8'):
import sys
if [x for x in (sys.stdin,sys.stdout,sys.stderr) if x.encoding is None] :
import os
defEnc = None
if defEnc is None :
try:
import locale
defEnc = locale.getpreferredencoding()
except: pass
if defEnc is None :
try: defEnc = sys.getfilesystemencoding()
except: pass
if defEnc is None :
try: defEnc = sys.stdin.encoding
except: pass
if defEnc is None :
defEnc = last_resort_default
os.environ['PYTHONIOENCODING'] = os.environ.get("PYTHONIOENCODING",defEnc)
os.execvpe(sys.argv[0],sys.argv,os.environ)
__fix_io_encoding() ; del __fix_io_encoding
Yes, it’s possible to get an infinite loop here if this “setenv” fails.
I just thought I’d mention something here which I had to spent a long time experimenting with before I finally realised what was going on. This may be so obvious to everyone here that they haven’t bothered mentioning it. But it would’ve helped me if they had, so on that principle…!
NB: I am using Jython specifically, v 2.7, so just possibly this may not apply to CPython…
NB2: the first two lines of my .py file here are:
# -*- coding: utf-8 -*-
from __future__ import print_function
The “%” (AKA “interpolation operator”) string construction mechanism causes ADDITIONAL problems too… If the default encoding of the “environment” is ASCII and you try to do something like
You will have no difficulty running in Eclipse… In a Windows CLI (DOS window) you will find that the encoding is code page 850 (my Windows 7 OS) or something similar, which can handle European accented characters at least, so it’ll work.
If, OTOH, you direct to a file from the CLI, the stdout encoding will be None, which will default to ASCII (on my OS anyway), which will not be able to handle either of the above prints… (dreaded encoding error).
So then you might think of redirecting your stdout by using
sys.stdout = codecs.getwriter('utf8')(sys.stdout)
and try running in the CLI piping to a file… Very oddly, print A above will work… But print B above will throw the encoding error! The following will however work OK:
The conclusion I have come to (provisionally) is that if a string which is specified to be a Unicode string using the “u” prefix is submitted to the %-handling mechanism it appears to involve the use of the default environment encoding, regardless of whether you have set stdout to redirect!
How people deal with this is a matter of choice. I would welcome a Unicode expert to say why this happens, whether I’ve got it wrong in some way, what the preferred solution to this, whether it also applies to CPython, whether it happens in Python 3, etc., etc.
{"cmd":["python","-u","$file"],"file_regex":"^[ ]*File \"(...*?)\", line ([0-9]*)","selector":"source.python","encoding":"utf8","env":{"PYTHONIOENCODING":"utf-8","LANG":"en_US.UTF-8"}}
configure Configure gitsome.
create-comment Create a comment on the given issue.
create-issue Create an issue.
create-repo Create a repo.
emails List all the user's registered emails.
emojis List all GitHub supported emojis.
feed List all activity for the given user or repo.
followers List all followers and the total follower count.
following List all followed users and the total followed count.
gitignore-template Output the gitignore template for the given language.
gitignore-templates Output all supported gitignore templates.
issue Output detailed information about the given issue.
issues List all issues matching the filter.
license Output the license template for the given license.
licenses Output all supported license templates.
me List information about the logged in user.
notifications List all notifications.
octo Output an Easter egg or the given message from Octocat.
pull-request Output detailed information about the given pull request.
pull-requests List all pull requests.
rate-limit Output the rate limit. Not available for Enterprise.
repo Output detailed information about the given filter.
repos List all repos matching the given filter.
search-issues Search for all issues matching the given query.
search-repos Search for all repos matching the given query.
starred Output starred repos.
trending List trending repos for the given language.
user List information about the given user.
view View the given index in the terminal or a browser.
Copyright 2016 Donne Martin
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
This somewhat depends on what platform you are on. The most common way to do this is by printing ANSI escape sequences. For a simple example, here’s some python code from the blender build scripts:
print(bcolors.WARNING + "Warning: No active frommets remain. Continue?" + bcolors.ENDC)
or, with Python3.6+:
print(f"{bcolors.WARNING}Warning: No active frommets remain. Continue?{bcolors.ENDC}")
This will work on unixes including OS X, linux and windows (provided you use ANSICON, or in Windows 10 provided you enable VT100 emulation). There are ansi codes for setting the color, moving the cursor, and more.
If you are going to get complicated with this (and it sounds like you are if you are writing a game), you should look into the “curses” module, which handles a lot of the complicated parts of this for you. The Python Curses HowTO is a good introduction.
If you are not using extended ASCII (i.e. not on a PC), you are stuck with the ascii characters below 127, and ‘#’ or ‘@’ is probably your best bet for a block. If you can ensure your terminal is using a IBM extended ascii character set, you have many more options. Characters 176, 177, 178 and 219 are the “block characters”.
Some modern text-based programs, such as “Dwarf Fortress”, emulate text mode in a graphical mode, and use images of the classic PC font. You can find some of these bitmaps that you can use on the Dwarf Fortress Wiki see (user-made tilesets).
Hmm.. I think got a little carried away on this answer. I am in the midst of planning an epic text-based adventure game, though. Good luck with your colored text!
def print_format_table():"""
prints table of formatted text format options
"""for style in range(8):for fg in range(30,38):
s1 =''for bg in range(40,48):
format =';'.join([str(style), str(fg), str(bg)])
s1 +='\x1b[%sm %s \x1b[0m'%(format, format)print(s1)print('\n')
print_format_table()
Print a string that starts a color/style, then the string, then end the color/style change with '\x1b[0m':
print('\x1b[6;30;42m' + 'Success!' + '\x1b[0m')
Get a table of format options for shell text with following code:
def print_format_table():
"""
prints table of formatted text format options
"""
for style in range(8):
for fg in range(30,38):
s1 = ''
for bg in range(40,48):
format = ';'.join([str(style), str(fg), str(bg)])
s1 += '\x1b[%sm %s \x1b[0m' % (format, format)
print(s1)
print('\n')
print_format_table()
Define a string that starts a color and a string that ends the color, then print your text with the start string at the front and the end string at the end.
CRED = '\033[91m'
CEND = '\033[0m'
print(CRED + "Error, does not compute!" + CEND)
This produces the following in bash, in urxvt with a Zenburn-style color scheme:
import os
os.system("")# Group of Different functions for different stylesclass style():
BLACK ='\033[30m'
RED ='\033[31m'
GREEN ='\033[32m'
YELLOW ='\033[33m'
BLUE ='\033[34m'
MAGENTA ='\033[35m'
CYAN ='\033[36m'
WHITE ='\033[37m'
UNDERLINE ='\033[4m'
RESET ='\033[0m'print(style.YELLOW +"Hello, World!")
I’m responding because I have found out a way to use ANSI codes on Windows 10, so that you can change the colour of text without any modules that aren’t built in:
The line that makes this work is os.system(""), or any other system call, which allows you to print ANSI codes in the Terminal:
import os
os.system("")
# Group of Different functions for different styles
class style():
BLACK = '\033[30m'
RED = '\033[31m'
GREEN = '\033[32m'
YELLOW = '\033[33m'
BLUE = '\033[34m'
MAGENTA = '\033[35m'
CYAN = '\033[36m'
WHITE = '\033[37m'
UNDERLINE = '\033[4m'
RESET = '\033[0m'
print(style.YELLOW + "Hello, World!")
Note: Although this gives the same options as other Windows options, Windows does not full support ANSI codes, even with this trick. Not all the text decoration colours work and all the ‘bright’ colours (Codes 90-97 and 100-107) display the same as the regular colours (Codes 30-37 and 40-47)
Edit: Thanks to @j-l for finding an even shorter method.
tl;dr: Add os.system("") near the top of your file.
My favorite way is with the Blessings library (full disclosure: I wrote it). For example:
from blessings import Terminal
t = Terminal()
print t.red('This is red.')
print t.bold_bright_red_on_black('Bright red on black')
To print colored bricks, the most reliable way is to print spaces with background colors. I use this technique to draw the progress bar in nose-progressive:
print t.on_green(' ')
You can print in specific locations as well:
with t.location(0, 5):
print t.on_yellow(' ')
If you have to muck with other terminal capabilities in the course of your game, you can do that as well. You can use Python’s standard string formatting to keep it readable:
print '{t.clear_eol}You just cleared a {t.bold}whole{t.normal} line!'.format(t=t)
The nice thing about Blessings is that it does its best to work on all sorts of terminals, not just the (overwhelmingly common) ANSI-color ones. It also keeps unreadable escape sequences out of your code while remaining concise to use. Have fun!
from sty import fg, bg, ef, rs
foo = fg.red +'This is red text!'+ fg.rs
bar = bg.blue +'This has a blue background!'+ bg.rs
baz = ef.italic +'This is italic text'+ rs.italic
qux = fg(201)+'This is pink text using 8bit colors'+ fg.rs
qui = fg(255,10,10)+'This is red text using 24bit colors.'+ fg.rs
# Add custom colors:from sty importStyle,RgbFg
fg.orange =Style(RgbFg(255,150,50))
buf = fg.orange +'Yay, Im orange.'+ fg.rs
print(foo, bar, baz, qux, qui, buf, sep='\n')
sty is similar to colorama, but it’s less verbose, supports 8bit and 24bit (rgb) colors, allows you to register your own styles, supports muting, is really flexible, well documented and more.
Examples:
from sty import fg, bg, ef, rs
foo = fg.red + 'This is red text!' + fg.rs
bar = bg.blue + 'This has a blue background!' + bg.rs
baz = ef.italic + 'This is italic text' + rs.italic
qux = fg(201) + 'This is pink text using 8bit colors' + fg.rs
qui = fg(255, 10, 10) + 'This is red text using 24bit colors.' + fg.rs
# Add custom colors:
from sty import Style, RgbFg
fg.orange = Style(RgbFg(255, 150, 50))
buf = fg.orange + 'Yay, Im orange.' + fg.rs
print(foo, bar, baz, qux, qui, buf, sep='\n')
class colors:'''Colors class:
reset all colors with colors.reset
two subclasses fg for foreground and bg for background.
use as colors.subclass.colorname.
i.e. colors.fg.red or colors.bg.green
also, the generic bold, disable, underline, reverse, strikethrough,
and invisible work with the main class
i.e. colors.bold
'''
reset='\033[0m'
bold='\033[01m'
disable='\033[02m'
underline='\033[04m'
reverse='\033[07m'
strikethrough='\033[09m'
invisible='\033[08m'class fg:
black='\033[30m'
red='\033[31m'
green='\033[32m'
orange='\033[33m'
blue='\033[34m'
purple='\033[35m'
cyan='\033[36m'
lightgrey='\033[37m'
darkgrey='\033[90m'
lightred='\033[91m'
lightgreen='\033[92m'
yellow='\033[93m'
lightblue='\033[94m'
pink='\033[95m'
lightcyan='\033[96m'class bg:
black='\033[40m'
red='\033[41m'
green='\033[42m'
orange='\033[43m'
blue='\033[44m'
purple='\033[45m'
cyan='\033[46m'
lightgrey='\033[47m'
generated a class with all the colors using a for loop to iterate every combination of color up to 100, then wrote a class with python colors. Copy and paste as you will, GPLv2 by me:
class colors:
'''Colors class:
reset all colors with colors.reset
two subclasses fg for foreground and bg for background.
use as colors.subclass.colorname.
i.e. colors.fg.red or colors.bg.green
also, the generic bold, disable, underline, reverse, strikethrough,
and invisible work with the main class
i.e. colors.bold
'''
reset='\033[0m'
bold='\033[01m'
disable='\033[02m'
underline='\033[04m'
reverse='\033[07m'
strikethrough='\033[09m'
invisible='\033[08m'
class fg:
black='\033[30m'
red='\033[31m'
green='\033[32m'
orange='\033[33m'
blue='\033[34m'
purple='\033[35m'
cyan='\033[36m'
lightgrey='\033[37m'
darkgrey='\033[90m'
lightred='\033[91m'
lightgreen='\033[92m'
yellow='\033[93m'
lightblue='\033[94m'
pink='\033[95m'
lightcyan='\033[96m'
class bg:
black='\033[40m'
red='\033[41m'
green='\033[42m'
orange='\033[43m'
blue='\033[44m'
purple='\033[45m'
cyan='\033[46m'
lightgrey='\033[47m'
import ctypes
# Constants from the Windows API
STD_OUTPUT_HANDLE =-11
FOREGROUND_RED =0x0004# text color contains red.def get_csbi_attributes(handle):# Based on IPython's winconsole.py, written by Alexander Belchenkoimport struct
csbi = ctypes.create_string_buffer(22)
res = ctypes.windll.kernel32.GetConsoleScreenBufferInfo(handle, csbi)assert res
(bufx, bufy, curx, cury, wattr,
left, top, right, bottom, maxx, maxy)= struct.unpack("hhhhHhhhhhh", csbi.raw)return wattr
handle = ctypes.windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
reset = get_csbi_attributes(handle)
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, FOREGROUND_RED)print"Cherry on top"
ctypes.windll.kernel32.SetConsoleTextAttribute(handle, reset)
For the character to print like a box, it really depends on what font you are using for the console window. The pound symbol works well, but it depends on the font:
#
回答 15
# Pure Python 3.x demo, 256 colors# Works with bash under Linux and MacOS
fg =lambda text, color:"\33[38;5;"+ str(color)+"m"+ text +"\33[0m"
bg =lambda text, color:"\33[48;5;"+ str(color)+"m"+ text +"\33[0m"def print_six(row, format, end="\n"):for col in range(6):
color = row*6+ col -2if color>=0:
text ="{:3d}".format(color)print(format(text,color), end=" ")else:print(end=" ")# four spacesprint(end=end)for row in range(0,43):
print_six(row, fg," ")
print_six(row, bg)# Simple usage: print(fg("text", 160))
# Pure Python 3.x demo, 256 colors
# Works with bash under Linux and MacOS
fg = lambda text, color: "\33[38;5;" + str(color) + "m" + text + "\33[0m"
bg = lambda text, color: "\33[48;5;" + str(color) + "m" + text + "\33[0m"
def print_six(row, format, end="\n"):
for col in range(6):
color = row*6 + col - 2
if color>=0:
text = "{:3d}".format(color)
print (format(text,color), end=" ")
else:
print(end=" ") # four spaces
print(end=end)
for row in range(0, 43):
print_six(row, fg, " ")
print_six(row, bg)
# Simple usage: print(fg("text", 160))
回答 16
我最终这样做了,我觉得那是最干净的:
formatters ={'RED':'\033[91m','GREEN':'\033[92m','END':'\033[0m',}print'Master is currently {RED}red{END}!'.format(**formatters)print'Help make master {GREEN}green{END} again!'.format(**formatters)
fromColorItimport*# Use this to ensure that ColorIt will be usable by certain command line interfaces
initColorIt()# Foregroundprint(color ('This text is red', colors.RED))print(color ('This text is orange', colors.ORANGE))print(color ('This text is yellow', colors.YELLOW))print(color ('This text is green', colors.GREEN))print(color ('This text is blue', colors.BLUE))print(color ('This text is purple', colors.PURPLE))print(color ('This text is white', colors.WHITE))# Backgroundprint(background ('This text has a background that is red', colors.RED))print(background ('This text has a background that is orange', colors.ORANGE))print(background ('This text has a background that is yellow', colors.YELLOW))print(background ('This text has a background that is green', colors.GREEN))print(background ('This text has a background that is blue', colors.BLUE))print(background ('This text has a background that is purple', colors.PURPLE))print(background ('This text has a background that is white', colors.WHITE))# Customprint(color ("This color has a custom grey text color",(150,150,150))print(background ("This color has a custom grey background",(150,150,150))# Combinationprint(background (color ("This text is blue with a white background", colors.BLUE), colors.WHITE))
from ColorIt import *
# Use this to ensure that ColorIt will be usable by certain command line interfaces
initColorIt()
# Foreground
print (color ('This text is red', colors.RED))
print (color ('This text is orange', colors.ORANGE))
print (color ('This text is yellow', colors.YELLOW))
print (color ('This text is green', colors.GREEN))
print (color ('This text is blue', colors.BLUE))
print (color ('This text is purple', colors.PURPLE))
print (color ('This text is white', colors.WHITE))
# Background
print (background ('This text has a background that is red', colors.RED))
print (background ('This text has a background that is orange', colors.ORANGE))
print (background ('This text has a background that is yellow', colors.YELLOW))
print (background ('This text has a background that is green', colors.GREEN))
print (background ('This text has a background that is blue', colors.BLUE))
print (background ('This text has a background that is purple', colors.PURPLE))
print (background ('This text has a background that is white', colors.WHITE))
# Custom
print (color ("This color has a custom grey text color", (150, 150, 150))
print (background ("This color has a custom grey background", (150, 150, 150))
# Combination
print (background (color ("This text is blue with a white background", colors.BLUE), colors.WHITE))
This gives you:
It’s also worth noting that this is cross platform and has been tested on mac, linux, and windows.
Note: Blinking, italics, bold, etc. will be added in a few days.
回答 24
如果您使用的是Windows,那么就到这里!
# display text on a Windows console# Windows XP with Python27 or Python32from ctypes import windll
# needed for Python2/Python3 difftry:
input = raw_input
except:pass
STD_OUTPUT_HANDLE =-11
stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)# look at the output and select the color you want# for instance hex E is yellow on black# hex 1E is yellow on blue# hex 2E is yellow on green and so onfor color in range(0,75):
windll.kernel32.SetConsoleTextAttribute(stdout_handle, color)print("%X --> %s"%(color,"Have a fine day!"))
input("Press Enter to go on ... ")
# display text on a Windows console
# Windows XP with Python27 or Python32
from ctypes import windll
# needed for Python2/Python3 diff
try:
input = raw_input
except:
pass
STD_OUTPUT_HANDLE = -11
stdout_handle = windll.kernel32.GetStdHandle(STD_OUTPUT_HANDLE)
# look at the output and select the color you want
# for instance hex E is yellow on black
# hex 1E is yellow on blue
# hex 2E is yellow on green and so on
for color in range(0, 75):
windll.kernel32.SetConsoleTextAttribute(stdout_handle, color)
print("%X --> %s" % (color, "Have a fine day!"))
input("Press Enter to go on ... ")
"""
.. versionadded:: 0.9.2
Functions for wrapping strings in ANSI color codes.
Each function within this module returns the input string ``text``, wrapped
with ANSI color codes for the appropriate color.
For example, to print some text as green on supporting terminals::
from fabric.colors import green
print(green("This text is green!"))
Because these functions simply return modified strings, you can nest them::
from fabric.colors import red, green
print(red("This sentence is red, except for " + \
green("these words, which are green") + "."))
If ``bold`` is set to ``True``, the ANSI flag for bolding will be flipped on
for that particular invocation, which usually shows up as a bold or brighter
version of the original color on most terminals.
"""def _wrap_with(code):def inner(text, bold=False):
c = code
if bold:
c ="1;%s"% c
return"\033[%sm%s\033[0m"%(c, text)return inner
red = _wrap_with('31')
green = _wrap_with('32')
yellow = _wrap_with('33')
blue = _wrap_with('34')
magenta = _wrap_with('35')
cyan = _wrap_with('36')
white = _wrap_with('37')
"""
.. versionadded:: 0.9.2
Functions for wrapping strings in ANSI color codes.
Each function within this module returns the input string ``text``, wrapped
with ANSI color codes for the appropriate color.
For example, to print some text as green on supporting terminals::
from fabric.colors import green
print(green("This text is green!"))
Because these functions simply return modified strings, you can nest them::
from fabric.colors import red, green
print(red("This sentence is red, except for " + \
green("these words, which are green") + "."))
If ``bold`` is set to ``True``, the ANSI flag for bolding will be flipped on
for that particular invocation, which usually shows up as a bold or brighter
version of the original color on most terminals.
"""
def _wrap_with(code):
def inner(text, bold=False):
c = code
if bold:
c = "1;%s" % c
return "\033[%sm%s\033[0m" % (c, text)
return inner
red = _wrap_with('31')
green = _wrap_with('32')
yellow = _wrap_with('33')
blue = _wrap_with('34')
magenta = _wrap_with('35')
cyan = _wrap_with('36')
white = _wrap_with('37')
Look at the subprocess module in the standard library:
import subprocess
subprocess.run(["ls", "-l"])
The advantage of subprocess vs. system is that it is more flexible (you can get the stdout, stderr, the “real” status code, better error handling, etc…).
The official documentation recommends the subprocess module over the alternative os.system():
The subprocess module provides more powerful facilities for spawning new processes and retrieving their results; using that module is preferable to using this function [os.system()].
Here’s a summary of the ways to call external programs and the advantages and disadvantages of each:
os.system("some_command with args") passes the command and arguments to your system’s shell. This is nice because you can actually run multiple commands at once in this manner and set up pipes and input/output redirection. For example:
However, while this is convenient, you have to manually handle the escaping of shell characters such as spaces, etc. On the other hand, this also lets you run commands which are simply shell commands and not actually external programs. See the documentation.
stream = os.popen("some_command with args") will do the same thing as os.system except that it gives you a file-like object that you can use to access standard input/output for that process. There are 3 other variants of popen that all handle the i/o slightly differently. If you pass everything as a string, then your command is passed to the shell; if you pass them as a list then you don’t need to worry about escaping anything. See the documentation.
The Popen class of the subprocess module. This is intended as a replacement for os.popen but has the downside of being slightly more complicated by virtue of being so comprehensive. For example, you’d say:
but it is nice to have all of the options there in one unified class instead of 4 different popen functions. See the documentation.
The call function from the subprocess module. This is basically just like the Popen class and takes all of the same arguments, but it simply waits until the command completes and gives you the return code. For example:
If you’re on Python 3.5 or later, you can use the new subprocess.run function, which is a lot like the above but even more flexible and returns a CompletedProcess object when the command finishes executing.
The os module also has all of the fork/exec/spawn functions that you’d have in a C program, but I don’t recommend using them directly.
The subprocess module should probably be what you use.
Finally please be aware that for all methods where you pass the final command to be executed by the shell as a string and you are responsible for escaping it. There are serious security implications if any part of the string that you pass can not be fully trusted. For example, if a user is entering some/any part of the string. If you are unsure, only use these methods with constants. To give you a hint of the implications consider this code:
and imagine that the user enters something “my mama didnt love me && rm -rf /” which could erase the whole filesystem.
回答 2
典型的实现:
import subprocess
p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)for line in p.stdout.readlines():print line,
retval = p.wait()
import subprocess
p = subprocess.Popen('ls', shell=True, stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
for line in p.stdout.readlines():
print line,
retval = p.wait()
You are free to do what you want with the stdout data in the pipe. In fact, you can simply omit those parameters (stdout= and stderr=) and it’ll behave like os.system().
回答 3
关于从调用者中分离子进程的一些提示(在后台启动子进程)。
假设您要从CGI脚本开始一个长任务。也就是说,子进程的生存期应比CGI脚本执行进程的生存期长。
子流程模块文档中的经典示例是:
import subprocessimport sys# Some code here
pid = subprocess.Popen([sys.executable,"longtask.py"])# Call subprocess# Some more code here
Some hints on detaching the child process from the calling one (starting the child process in background).
Suppose you want to start a long task from a CGI script. That is, the child process should live longer than the CGI script execution process.
The classical example from the subprocess module documentation is:
import subprocess
import sys
# Some code here
pid = subprocess.Popen([sys.executable, "longtask.py"]) # Call subprocess
# Some more code here
The idea here is that you do not want to wait in the line ‘call subprocess’ until the longtask.py is finished. But it is not clear what happens after the line ‘some more code here’ from the example.
My target platform was FreeBSD, but the development was on Windows, so I faced the problem on Windows first.
On Windows (Windows XP), the parent process will not finish until the longtask.py has finished its work. It is not what you want in a CGI script. The problem is not specific to Python; in the PHP community the problems are the same.
The solution is to pass DETACHED_PROCESS Process Creation Flag to the underlying CreateProcess function in Windows API.
If you happen to have installed pywin32, you can import the flag from the win32process module, otherwise you should define it yourself:
/* UPD 2015.10.27 @eryksun in a comment below notes, that the semantically correct flag is CREATE_NEW_CONSOLE (0x00000010) */
On FreeBSD we have another problem: when the parent process is finished, it finishes the child processes as well. And that is not what you want in a CGI script either. Some experiments showed that the problem seemed to be in sharing sys.stdout. And the working solution was the following:
I have not checked the code on other platforms and do not know the reasons of the behaviour on FreeBSD. If anyone knows, please share your ideas. Googling on starting background processes in Python does not shed any light yet.
Note that this is dangerous, since the command isn’t cleaned. I leave it up to you to google for the relevant documentation on the ‘os’ and ‘sys’ modules. There are a bunch of functions (exec* and spawn*) that will do similar things.
If you want to return the results of the command, you can use os.popen. However, this is deprecated since version 2.6 in favor of the subprocess module, which other answers have covered well.
subprocess.run(["ls","-l"])# Run command
subprocess.run(["ls","-l"], stdout=subprocess.PIPE)# This will run the command and return any output
subprocess.run(shlex.split("ls -l"))# You can also use the shlex library to split the command
pexpect.run("ls -l")# Run command as normal
child = pexpect.spawn('scp foo user@example.com:.')# Spawns child application
child.expect('Password:')# When this is the output
child.sendline('mypassword')
There are lots of different libraries which allow you to call external commands with Python. For each library I’ve given a description and shown an example of calling an external command. The command I used as the example is ls -l (list all files). If you want to find out more about any of the libraries I’ve listed and linked the documentation for each of them.
Hopefully this will help you make a decision on which library to use :)
subprocess
Subprocess allows you to call external commands and connect them to their input/output/error pipes (stdin, stdout, and stderr). Subprocess is the default choice for running commands, but sometimes other modules are better.
subprocess.run(["ls", "-l"]) # Run command
subprocess.run(["ls", "-l"], stdout=subprocess.PIPE) # This will run the command and return any output
subprocess.run(shlex.split("ls -l")) # You can also use the shlex library to split the command
os
os is used for “operating system dependent functionality”. It can also be used to call external commands with os.system and os.popen (Note: There is also a subprocess.popen). os will always run the shell and is a simple alternative for people who don’t need to, or don’t know how to use subprocess.run.
os.system("ls -l") # run command
os.popen("ls -l").read() # This will run the command and return any output
sh
sh is a subprocess interface which lets you call programs as if they were functions. This is useful if you want to run a command multiple times.
sh.ls("-l") # Run command normally
ls_cmd = sh.Command("ls") # Save command as a variable
ls_cmd() # Run command as if it were a function
plumbum
plumbum is a library for “script-like” Python programs. You can call programs like functions as in sh. Plumbum is useful if you want to run a pipeline without the shell.
ls_cmd = plumbum.local("ls -l") # get command
ls_cmd() # run command
pexpect
pexpect lets you spawn child applications, control them and find patterns in their output. This is a better alternative to subprocess for commands that expect a tty on Unix.
pexpect.run("ls -l") # Run command as normal
child = pexpect.spawn('scp foo user@example.com:.') # Spawns child application
child.expect('Password:') # When this is the output
child.sendline('mypassword')
fabric
fabric is a Python 2.5 and 2.7 library. It allows you to execute local and remote shell commands. Fabric is simple alternative for running commands in a secure shell (SSH)
fabric.operations.local('ls -l') # Run command as normal
fabric.operations.local('ls -l', capture = True) # Run command and receive output
envoy
envoy is known as “subprocess for humans”. It is used as a convenience wrapper around the subprocess module.
r = envoy.run("ls -l") # Run command
r.std_out # get output
commands
commands contains wrapper functions for os.popen, but it has been removed from Python 3 since subprocess is a better alternative.
The edit was based on J.F. Sebastian’s comment.
回答 8
我总是用fabric这样的东西:
from fabric.operations importlocal
result =local('ls', capture=True)print"Content:/n%s"%(result,)
It is the recommended standard way. However, more complicated tasks (pipes, output, input, etc.) can be tedious to construct and write.
Note on Python version: If you are still using Python 2, subprocess.call works in a similar way.
ProTip: shlex.split can help you to parse the command for run, call, and other subprocess functions in case you don’t want (or you can’t!) provide them in form of lists:
If shell is True, the specified command will be executed through the shell. This can be useful if you are using Python primarily for the enhanced control flow it offers over most system shells and still want convenient access to other shell features such as shell pipes, filename wildcards, environment variable expansion, and expansion of ~ to a user’s home directory. However, note that Python itself offers implementations of many shell-like features (in particular, glob, fnmatch, os.walk(), os.path.expandvars(), os.path.expanduser(), and shutil).
subprocess.run is the recommended approach as of Python 3.5 if your code does not need to maintain compatibility with earlier Python versions. It’s more consistent and offers similar ease-of-use as Envoy. (Piping isn’t as straightforward though. See this question for how.)
I recommend trying Envoy. It’s a wrapper for subprocess, which in turn aims to replace the older modules and functions. Envoy is subprocess for humans.
As of Python 3.5, the documentation recommends subprocess.run:
The recommended approach to invoking subprocesses is to use the run() function for all use cases it can handle. For more advanced use cases, the underlying Popen interface can be used directly.
Here’s an example of the simplest possible usage – and it does exactly as asked:
run waits for the command to successfully finish, then returns a CompletedProcess object. It may instead raise TimeoutExpired (if you give it a timeout= argument) or CalledProcessError (if it fails and you pass check=True).
As you might infer from the above example, stdout and stderr both get piped to your own stdout and stderr by default.
We can inspect the returned object and see the command that was given and the returncode:
(I find it interesting and slightly counterintuitive that the version info gets put to stderr instead of stdout.)
Pass a command list
One might easily move from manually providing a command string (like the question suggests) to providing a string built programmatically. Don’t build strings programmatically. This is a potential security issue. It’s better to assume you don’t trust the input.
>>> import textwrap
>>> args = ['python', textwrap.__file__]
>>> cp = subprocess.run(args, stdout=subprocess.PIPE)
>>> cp.stdout
b'Hello there.\r\n This is indented.\r\n'
Note, only args should be passed positionally.
Full Signature
Here’s the actual signature in the source and as shown by help(run):
The popenargs and kwargs are given to the Popen constructor. input can be a string of bytes (or unicode, if specify encoding or universal_newlines=True) that will be piped to the subprocess’s stdin.
The documentation describes timeout= and check=True better than I could:
The timeout argument is passed to Popen.communicate(). If the timeout
expires, the child process will be killed and waited for. The
TimeoutExpired exception will be re-raised after the child process has
terminated.
If check is true, and the process exits with a non-zero exit code, a
CalledProcessError exception will be raised. Attributes of that
exception hold the arguments, the exit code, and stdout and stderr if
they were captured.
and this example for check=True is better than one I could come up with:
>>> subprocess.run("exit 1", shell=True, check=True)
Traceback (most recent call last):
...
subprocess.CalledProcessError: Command 'exit 1' returned non-zero exit status 1
Expanded Signature
Here’s an expanded signature, as given in the documentation:
Note that this indicates that only the args list should be passed positionally. So pass the remaining arguments as keyword arguments.
Popen
When use Popen instead? I would struggle to find use-case based on the arguments alone. Direct usage of Popen would, however, give you access to its methods, including poll, ‘send_signal’, ‘terminate’, and ‘wait’.
Here’s the Popen signature as given in the source. I think this is the most precise encapsulation of the information (as opposed to help(Popen)):
Execute a child program in a new process. On POSIX, the class uses
os.execvp()-like behavior to execute the child program. On Windows,
the class uses the Windows CreateProcess() function. The arguments to
Popen are as follows.
Understanding the remaining documentation on Popen will be left as an exercise for the reader.
os.system is OK, but kind of dated. It’s also not very secure. Instead, try subprocess. subprocess does not call sh directly and is therefore more secure than os.system.
>>>from plumbum importlocal>>> ls =local["ls"]>>> ls
LocalCommand(<LocalPath/bin/ls>)>>> ls()
u'build.py\ndist\ndocs\nLICENSE\nplumbum\nREADME.rst\nsetup.py\ntests\ntodo.txt\n'>>> notepad =local["c:\\windows\\notepad.exe"]>>> notepad()# Notepad window pops up
u''# Notepad window is closed by user, command returns
There is another difference here which is not mentioned previously.
subprocess.Popen executes the <command> as a subprocess. In my case, I need to execute file <a> which needs to communicate with another program, <b>.
I tried subprocess, and execution was successful. However <b> could not communicate with <a>.
Everything is normal when I run both from the terminal.
One more:
(NOTE: kwrite behaves different from other applications. If you try the below with Firefox, the results will not be the same.)
If you try os.system("kwrite"), program flow freezes until the user closes kwrite. To overcome that I tried instead os.system(konsole -e kwrite). This time program continued to flow, but kwrite became the subprocess of the console.
Anyone runs the kwrite not being a subprocess (i.e. in the system monitor it must appear at the leftmost edge of the tree).
It’s basically a wrapper for popen and shlex for now. It also supports piping commands so you can chain commands easier in Python. So you can do things like:
In Windows you can just import the subprocess module and run external commands by calling subprocess.Popen(), subprocess.Popen().communicate() and subprocess.Popen().wait() as below:
# Python script to run a command line
import subprocess
def execute(cmd):
"""
Purpose : To execute a command and return exit status
Argument : cmd - command to execute
Return : exit_code
"""
process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE, stderr=subprocess.PIPE)
(result, error) = process.communicate()
rc = process.wait()
if rc != 0:
print "Error: failed to execute command:", cmd
print error
return result
# def
command = "tasklist | grep python"
print "This process detail: \n", execute(command)
Output:
This process detail:
python.exe 604 RDP-Tcp#0 4 5,660 K
Under Linux, in case you would like to call an external command that will execute independently (will keep running after the python script terminates), you can use a simple queue as task spooler or the at command
An example with task spooler:
import os
os.system('ts <your-command>')
Notes about task spooler (ts):
You could set the number of concurrent processes to be run (“slots”) with:
ts -S <number-of-slots>
Installing ts doesn’t requires admin privileges. You can download and compile it from source with a simple make, add it to your path and you’re done.
回答 28
您可以使用Popen,然后可以检查过程的状态:
from subprocess importPopen
proc =Popen(['ls','-l'])if proc.poll()isNone:
proc.kill()