分类目录归档:知识问答

Python中的最大递归深度是多少,以及如何增加?

问题:Python中的最大递归深度是多少,以及如何增加?

我在这里有这个尾部递归函数:

def recursive_function(n, sum):
    if n < 1:
        return sum
    else:
        return recursive_function(n-1, sum+n)

c = 998
print(recursive_function(c, 0))

它工作到了n=997,然后它破裂并吐出了RecursionError: maximum recursion depth exceeded in comparison。这仅仅是堆栈溢出吗?有办法解决吗?

I have this tail recursive function here:

def recursive_function(n, sum):
    if n < 1:
        return sum
    else:
        return recursive_function(n-1, sum+n)

c = 998
print(recursive_function(c, 0))

It works up to n=997, then it just breaks and spits out a RecursionError: maximum recursion depth exceeded in comparison. Is this just a stack overflow? Is there a way to get around it?


回答 0

这是防止堆栈溢出的保护措施,是的。Python(或更确切地说,CPython实现)无法优化尾部递归,无限制的递归会导致堆栈溢出。您可以使用来检查递归限制,sys.getrecursionlimit并使用来更改递归限制sys.setrecursionlimit,但是这样做很危险-标准限制有些保守,但是Python堆栈框架可能会很大。

Python不是一种功能语言,尾部递归并不是一种特别有效的技术。如果可能的话,迭代地重写算法通常是一个更好的主意。

It is a guard against a stack overflow, yes. Python (or rather, the CPython implementation) doesn’t optimize tail recursion, and unbridled recursion causes stack overflows. You can check the recursion limit with sys.getrecursionlimit and change the recursion limit with sys.setrecursionlimit, but doing so is dangerous — the standard limit is a little conservative, but Python stackframes can be quite big.

Python isn’t a functional language and tail recursion is not a particularly efficient technique. Rewriting the algorithm iteratively, if possible, is generally a better idea.


回答 1

看起来您只需要设置更高的递归深度即可

import sys
sys.setrecursionlimit(1500)

Looks like you just need to set a higher recursion depth:

import sys
sys.setrecursionlimit(1500)

回答 2

这是为了避免堆栈溢出。Python解释器限制了递归的深度,以帮助您避免无限递归,从而导致堆栈溢出。尝试增加递归限制(sys.setrecursionlimit)或不递归地重写代码。

Python文档中

sys.getrecursionlimit()

返回递归限制的当前值,即Python解释器堆栈的最大深度。此限制可防止无限递归导致C堆栈溢出和Python崩溃。可以通过设置setrecursionlimit()

It’s to avoid a stack overflow. The Python interpreter limits the depths of recursion to help you avoid infinite recursions, resulting in stack overflows. Try increasing the recursion limit (sys.setrecursionlimit) or re-writing your code without recursion.

From the Python documentation:

sys.getrecursionlimit()

Return the current value of the recursion limit, the maximum depth of the Python interpreter stack. This limit prevents infinite recursion from causing an overflow of the C stack and crashing Python. It can be set by setrecursionlimit().


回答 3

如果您经常需要更改递归限制(例如,在解决编程难题时),则可以定义一个简单的上下文管理器,如下所示:

import sys

class recursionlimit:
    def __init__(self, limit):
        self.limit = limit
        self.old_limit = sys.getrecursionlimit()

    def __enter__(self):
        sys.setrecursionlimit(self.limit)

    def __exit__(self, type, value, tb):
        sys.setrecursionlimit(self.old_limit)

然后要调用具有自定义限制的函数,您可以执行以下操作:

with recursionlimit(1500):
    print(fib(1000, 0))

with语句主体退出时,递归限制将恢复为默认值。

If you often need to change the recursion limit (e.g. while solving programming puzzles) you can define a simple context manager like this:

import sys

class recursionlimit:
    def __init__(self, limit):
        self.limit = limit
        self.old_limit = sys.getrecursionlimit()

    def __enter__(self):
        sys.setrecursionlimit(self.limit)

    def __exit__(self, type, value, tb):
        sys.setrecursionlimit(self.old_limit)

Then to call a function with a custom limit you can do:

with recursionlimit(1500):
    print(fib(1000, 0))

On exit from the body of the with statement the recursion limit will be restored to the default value.


回答 4

使用保证尾叫优化的语言。或使用迭代。另外,也可以和装饰工一起变得可爱。

Use a language that guarantees tail-call optimisation. Or use iteration. Alternatively, get cute with decorators.


回答 5

resource.setrlimit 还必须用于增加堆栈大小并防止段错误

Linux内核限制了进程的堆栈

Python将局部变量存储在解释器的堆栈中,因此递归会占用解释器的堆栈空间。

如果Python解释器试图超过堆栈限制,则Linux内核会使其出现分段错误。

堆栈限制大小由getrlimitsetrlimit系统调用控制。

Python通过resource模块提供对那些系统调用的访问。

import resource
import sys

print resource.getrlimit(resource.RLIMIT_STACK)
print sys.getrecursionlimit()
print

# Will segfault without this line.
resource.setrlimit(resource.RLIMIT_STACK, [0x10000000, resource.RLIM_INFINITY])
sys.setrecursionlimit(0x100000)

def f(i):
    print i
    sys.stdout.flush()
    f(i + 1)
f(0)

当然,如果您继续增加ulimit,RAM将会用完,这将使计算机因交换疯狂而停止运行,或者通过OOM Killer杀死Python。

在bash中,您可以使用以下命令查看和设置堆栈限制(以kb为单位):

ulimit -s
ulimit -s 10000

我的默认值为8Mb。

也可以看看:

已在Ubuntu 16.10,Python 2.7.12上测试。

resource.setrlimit must also be used to increase the stack size and prevent segfault

The Linux kernel limits the stack of processes.

Python stores local variables on the stack of the interpreter, and so recursion takes up stack space of the interpreter.

If the Python interpreter tries to go over the stack limit, the Linux kernel makes it segmentation fault.

The stack limit size is controlled with the getrlimit and setrlimit system calls.

Python offers access to those system calls through the resource module.

import resource
import sys

print resource.getrlimit(resource.RLIMIT_STACK)
print sys.getrecursionlimit()
print

# Will segfault without this line.
resource.setrlimit(resource.RLIMIT_STACK, [0x10000000, resource.RLIM_INFINITY])
sys.setrecursionlimit(0x100000)

def f(i):
    print i
    sys.stdout.flush()
    f(i + 1)
f(0)

Of course, if you keep increasing ulimit, your RAM will run out, which will either slow your computer to a halt due to swap madness, or kill Python via the OOM Killer.

From bash, you can see and set the stack limit (in kb) with:

ulimit -s
ulimit -s 10000

The default value for me is 8Mb.

See also:

Tested on Ubuntu 16.10, Python 2.7.12.


回答 6

我意识到这是一个老问题,但是对于那些阅读者,我建议不要对此类问题使用递归-列表要快得多,并且完全避免递归。我将其实现为:

def fibonacci(n):
    f = [0,1,1]
    for i in xrange(3,n):
        f.append(f[i-1] + f[i-2])
    return 'The %.0fth fibonacci number is: %.0f' % (n,f[-1])

(如果您开始从0而不是1开始计数斐波那契数列,请在xrange中使用n + 1。)

I realize this is an old question but for those reading, I would recommend against using recursion for problems such as this – lists are much faster and avoid recursion entirely. I would implement this as:

def fibonacci(n):
    f = [0,1,1]
    for i in xrange(3,n):
        f.append(f[i-1] + f[i-2])
    return 'The %.0fth fibonacci number is: %.0f' % (n,f[-1])

(Use n+1 in xrange if you start counting your fibonacci sequence from 0 instead of 1.)


回答 7

当然,可以通过应用Binet公式在O(n)中计算斐波那契数:

from math import floor, sqrt

def fib(n):                                                     
    return int(floor(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))+0.5))

正如评论者所指出的,由于,它不是O(1)而是O(n)2**n。另外一个区别是,您只获得一个值,而使用递归时,您将获得该值之前的所有值Fibonacci(n)

Of course Fibonacci numbers can be computed in O(n) by applying the Binet formula:

from math import floor, sqrt

def fib(n):                                                     
    return int(floor(((1+sqrt(5))**n-(1-sqrt(5))**n)/(2**n*sqrt(5))+0.5))

As the commenters note it’s not O(1) but O(n) because of 2**n. Also a difference is that you only get one value, while with recursion you get all values of Fibonacci(n) up to that value.


回答 8

错误“超出最大递归深度”时,我遇到了类似的问题。我发现错误是由我遍历的目录中的损坏文件触发的os.walk。如果您无法解决此问题,并且正在使用文件路径,请确保将其范围缩小,因为它可能是损坏的文件。

I had a similar issue with the error “Max recursion depth exceeded”. I discovered the error was being triggered by a corrupt file in the directory I was looping over with os.walk. If you have trouble solving this issue and you are working with file paths, be sure to narrow it down, as it might be a corrupt file.


回答 9

如果只想得到几个斐波那契数,则可以使用矩阵法。

from numpy import matrix

def fib(n):
    return (matrix('0 1; 1 1', dtype='object') ** n).item(1)

由于numpy使用快速指数运算算法,因此速度很快。您会在O(log n)中得到答案。它比Binet的公式更好,因为它仅使用整数。但是,如果您希望所有斐波那契数均不超过n,那么最好通过记忆来实现。

If you want to get only few Fibonacci numbers, you can use matrix method.

from numpy import matrix

def fib(n):
    return (matrix('0 1; 1 1', dtype='object') ** n).item(1)

It’s fast as numpy uses fast exponentiation algorithm. You get answer in O(log n). And it’s better than Binet’s formula because it uses only integers. But if you want all Fibonacci numbers up to n, then it’s better to do it by memorisation.


回答 10

使用生成器?

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fibs = fib() #seems to be the only way to get the following line to work is to
             #assign the infinite generator to a variable

f = [fibs.next() for x in xrange(1001)]

for num in f:
        print num

上面的fib()函数改编自:http : //intermediatepythonista.com/python-generators

Use generators?

def fib():
    a, b = 0, 1
    while True:
        yield a
        a, b = b, a + b

fibs = fib() #seems to be the only way to get the following line to work is to
             #assign the infinite generator to a variable

f = [fibs.next() for x in xrange(1001)]

for num in f:
        print num

above fib() function adapted from: http://intermediatepythonista.com/python-generators


回答 11

正如@alex 建议的那样,您可以使用生成器函数按顺序执行此操作,而不必递归执行。

这与您问题中的代码等效:

def fib(n):
    def fibseq(n):
        """ Iteratively return the first n Fibonacci numbers, starting from 0. """
        a, b = 0, 1
        for _ in xrange(n):
            yield a
            a, b = b, a + b

    return sum(v for v in fibseq(n))

print format(fib(100000), ',d')  # -> no recursion depth error

As @alex suggested, you could use a generator function to do this sequentially instead of recursively.

Here’s the equivalent of the code in your question:

def fib(n):
    def fibseq(n):
        """ Iteratively return the first n Fibonacci numbers, starting from 0. """
        a, b = 0, 1
        for _ in xrange(n):
            yield a
            a, b = b, a + b

    return sum(v for v in fibseq(n))

print format(fib(100000), ',d')  # -> no recursion depth error

回答 12

许多人建议增加递归限制是一个很好的解决方案,但并不是因为总会有限制。而是使用迭代解决方案。

def fib(n):
    a,b = 1,1
    for i in range(n-1):
        a,b = b,a+b
    return a
print fib(5)

Many recommend that increasing recursion limit is a good solution however it is not because there will be always limit. Instead use an iterative solution.

def fib(n):
    a,b = 1,1
    for i in range(n-1):
        a,b = b,a+b
    return a
print fib(5)

回答 13

我想给你一个使用记忆来计算斐波那契的例子,因为这将允许您使用递归来计算更大的数字:

cache = {}
def fib_dp(n):
    if n in cache:
        return cache[n]
    if n == 0: return 0
    elif n == 1: return 1
    else:
        value = fib_dp(n-1) + fib_dp(n-2)
    cache[n] = value
    return value

print(fib_dp(998))

这仍然是递归的,但是使用了一个简单的哈希表,该哈希表允许重新使用先前计算的斐波那契数,而不是再次进行处理。

I wanted to give you an example for using memoization to compute Fibonacci as this will allow you to compute significantly larger numbers using recursion:

cache = {}
def fib_dp(n):
    if n in cache:
        return cache[n]
    if n == 0: return 0
    elif n == 1: return 1
    else:
        value = fib_dp(n-1) + fib_dp(n-2)
    cache[n] = value
    return value

print(fib_dp(998))

This is still recursive, but uses a simple hashtable that allows the reuse of previously calculated Fibonacci numbers instead of doing them again.


回答 14

import sys
sys.setrecursionlimit(1500)

def fib(n, sum):
    if n < 1:
        return sum
    else:
        return fib(n-1, sum+n)

c = 998
print(fib(c, 0))
import sys
sys.setrecursionlimit(1500)

def fib(n, sum):
    if n < 1:
        return sum
    else:
        return fib(n-1, sum+n)

c = 998
print(fib(c, 0))

回答 15

我们可以使用@lru_cache装饰器和setrecursionlimit()方法来做到这一点:

import sys
from functools import lru_cache

sys.setrecursionlimit(15000)


@lru_cache(128)
def fib(n: int) -> int:
    if n == 0:
        return 0
    if n == 1:
        return 1

    return fib(n - 2) + fib(n - 1)


print(fib(14000))

输出量

30024687611784610909954941797150256486927479374907929434683754295022302429422848358634023335752162178658116387303893522391813423077567204146193912177985425759965410810605019053021570190026149647173108088094786756027114403612415007326991458343778563263940370716662743216573053208040553070210197932517628308167015873869948880323622321982198435498652758806996123592751252434571324967728548865087033966433650424543330098020063842868595816492963908030032326548984645615892344451398632426062857115917462228808073910572119126558184997987209873025407120679598408021068497765475222474299046183573947717256532535593461952826012850191693602073551792238148571064052850079975476925463787570629995816578671884209957706505655213778743330859631234442589530527514612069776150795114358628796784390811755362655769771068650740995128972351005382411964458155682913778466563529792280989115666759565256441826456081786038371722278388967254256057199423000376505262314868810660373978669420138382967692847455277784392729950672314920693691302891547531323138832943985935078735556672110054220032041561548590315294621529531199575971957359536867988711311482550501404508450342400953050944499115785985396588557041582402218095280101794144934995834735688732530679216395139965967382758179096248575936932919808413032911456135664665752332836514201349157649613728759338222629534204445483491804365831832919448755994772408147745801871446379654872505781349904024433656779853884819614924449819945230342456197818533654765527194609607959296668836657042938973102012760116580743591941893596607924960274722264285715479716022598086974414353585784805898377669116842002756368891922547626785125970004526761913744759327966638428657446582649249137716764154041799200960747515164228729976654250474574283272762300592961327227879153001050020190062933200829553787159082636533777550311557940634505157310094024075846831328702063769940259207902985911442136599426686220621914413462000983429439551695225325742716449543602174724585214896718594652325684194041820439660922117443726997973759660480107754534446001535247722384014147895626514102898089949605331327595320928957794069409252529061666121536998507599337628979471759721478687840083202475862103785567113327394632779402552890479623233069460683818874460463877452479256752401829811908362649646406120699094586824433927299460840993120477529668064393314036639349699429580222379452059925811788036061569820343853471827665733517687496651725499086383376119531998081619378853667092850432765957264840681380911889146981517031227737267252613705423551621181643027288122591924764289387307241098259223319732561050912005515665813505080619227629100785282198699132141465755572491992636342411653522265707496189070505531154683066691844859102698062258945308098231022792317500616520425607725305767131486478587056496429077806032476806802362362202208266406656599026501804747607137957607601654671

资源

functools lru_cache

We can do that using @lru_cache decorator and setrecursionlimit() method:

import sys
from functools import lru_cache

sys.setrecursionlimit(15000)


@lru_cache(128)
def fib(n: int) -> int:
    if n == 0:
        return 0
    if n == 1:
        return 1

    return fib(n - 2) + fib(n - 1)


print(fib(14000))

Output

3002468761178461090995494179715025648692747937490792943468375429502230242942284835863402333575216217865811638730389352239181342307756720414619391217798542575996541081060501905302157019002614964717310808809478675602711440361241500732699145834377856326394037071666274321657305320804055307021019793251762830816701587386994888032362232198219843549865275880699612359275125243457132496772854886508703396643365042454333009802006384286859581649296390803003232654898464561589234445139863242606285711591746222880807391057211912655818499798720987302540712067959840802106849776547522247429904618357394771725653253559346195282601285019169360207355179223814857106405285007997547692546378757062999581657867188420995770650565521377874333085963123444258953052751461206977615079511435862879678439081175536265576977106865074099512897235100538241196445815568291377846656352979228098911566675956525644182645608178603837172227838896725425605719942300037650526231486881066037397866942013838296769284745527778439272995067231492069369130289154753132313883294398593507873555667211005422003204156154859031529462152953119957597195735953686798871131148255050140450845034240095305094449911578598539658855704158240221809528010179414493499583473568873253067921639513996596738275817909624857593693291980841303291145613566466575233283651420134915764961372875933822262953420444548349180436583183291944875599477240814774580187144637965487250578134990402443365677985388481961492444981994523034245619781853365476552719460960795929666883665704293897310201276011658074359194189359660792496027472226428571547971602259808697441435358578480589837766911684200275636889192254762678512597000452676191374475932796663842865744658264924913771676415404179920096074751516422872997665425047457428327276230059296132722787915300105002019006293320082955378715908263653377755031155794063450515731009402407584683132870206376994025920790298591144213659942668622062191441346200098342943955169522532574271644954360217472458521489671859465232568419404182043966092211744372699797375966048010775453444600153524772238401414789562651410289808994960533132759532092895779406940925252906166612153699850759933762897947175972147868784008320247586210378556711332739463277940255289047962323306946068381887446046387745247925675240182981190836264964640612069909458682443392729946084099312047752966806439331403663934969942958022237945205992581178803606156982034385347182766573351768749665172549908638337611953199808161937885366709285043276595726484068138091188914698151703122773726725261370542355162118164302728812259192476428938730724109825922331973256105091200551566581350508061922762910078528219869913214146575557249199263634241165352226570749618907050553115468306669184485910269806225894530809823102279231750061652042560772530576713148647858705369649642907780603247428680176236527220826640665659902650188140474762163503557640566711903907798932853656216227739411210513756695569391593763704981001125

Source

functools lru_cache


回答 16

我们还可以使用动态编程自底向上方法的变体

def fib_bottom_up(n):

    bottom_up = [None] * (n+1)
    bottom_up[0] = 1
    bottom_up[1] = 1

    for i in range(2, n+1):
        bottom_up[i] = bottom_up[i-1] + bottom_up[i-2]

    return bottom_up[n]

print(fib_bottom_up(20000))

We could also use a variation of dynamic programming bottom up approach

def fib_bottom_up(n):

    bottom_up = [None] * (n+1)
    bottom_up[0] = 1
    bottom_up[1] = 1

    for i in range(2, n+1):
        bottom_up[i] = bottom_up[i-1] + bottom_up[i-2]

    return bottom_up[n]

print(fib_bottom_up(20000))

如何确定我的python shell是在OS X上以32位还是64位模式执行?

问题:如何确定我的python shell是在OS X上以32位还是64位模式执行?

我需要一种方法,从外壳程序中告诉外壳程序处于哪种模式。

我尝试查看平台模块,但似乎只告诉您“有关可执行文件所用的位体系结构和链接格式”的信息:尽管二进制文件编译为64位(我在OS X 10.6上运行),所以即使我使用此处介绍的方法强制使用32位模式,它似乎总是报告64 位。

I need a way to tell what mode the shell is in from within the shell.

I’ve tried looking at the platform module but it seems only to tell you about “about the bit architecture and the linkage format used for the executable”: the binary is compiled as 64bit though (I’m running on OS X 10.6) so it seems to always report 64bit even though I’m using the methods described here to force 32bit mode).


回答 0

一种方法是看sys.maxsize作为记录在这里

$ python-32 -c 'import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)'
('7fffffff', False)
$ python-64 -c 'import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)'
('7fffffffffffffff', True)

sys.maxsize是Python 2.6中引入的。如果您需要针对较旧系统的测试,则此稍微复杂一些的测试应适用于所有Python 2和3版本:

$ python-32 -c 'import struct;print( 8 * struct.calcsize("P"))'
32
$ python-64 -c 'import struct;print( 8 * struct.calcsize("P"))'
64

顺便说一句,您可能会想使用platform.architecture()它。不幸的是,其结果并不总是可靠的,特别是在OS X通用二进制文件的情况下

$ arch -x86_64 /usr/bin/python2.6 -c 'import sys,platform; print platform.architecture()[0], sys.maxsize > 2**32'
64bit True
$ arch -i386 /usr/bin/python2.6 -c 'import sys,platform; print platform.architecture()[0], sys.maxsize > 2**32'
64bit False

One way is to look at sys.maxsize as documented here:

$ python-32 -c 'import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)'
('7fffffff', False)
$ python-64 -c 'import sys;print("%x" % sys.maxsize, sys.maxsize > 2**32)'
('7fffffffffffffff', True)

sys.maxsize was introduced in Python 2.6. If you need a test for older systems, this slightly more complicated test should work on all Python 2 and 3 releases:

$ python-32 -c 'import struct;print( 8 * struct.calcsize("P"))'
32
$ python-64 -c 'import struct;print( 8 * struct.calcsize("P"))'
64

BTW, you might be tempted to use platform.architecture() for this. Unfortunately, its results are not always reliable, particularly in the case of OS X universal binaries.

$ arch -x86_64 /usr/bin/python2.6 -c 'import sys,platform; print platform.architecture()[0], sys.maxsize > 2**32'
64bit True
$ arch -i386 /usr/bin/python2.6 -c 'import sys,platform; print platform.architecture()[0], sys.maxsize > 2**32'
64bit False

回答 1

在终端/命令行中启动Python解释器时,您可能还会看到类似以下的行:

Python 2.7.2 (default, Jun 12 2011, 14:24:46) [MSC v.1500 64 bit (AMD64)] on win32

其中[MSC v.1500 64 bit (AMD64)]表示64位Python。适用于我的特定设置。

When starting the Python interpreter in the terminal/command line you may also see a line like:

Python 2.7.2 (default, Jun 12 2011, 14:24:46) [MSC v.1500 64 bit (AMD64)] on win32

Where [MSC v.1500 64 bit (AMD64)] means 64-bit Python. Works for my particular setup.


回答 2

基本上是马修·马歇尔(Matthew Marshall)回答的变体(带有来自标准库的结构):

import struct
print struct.calcsize("P") * 8

Basically a variant on Matthew Marshall’s answer (with struct from the std.library):

import struct
print struct.calcsize("P") * 8

回答 3

尝试使用ctypes获得void指针的大小:

import ctypes
print ctypes.sizeof(ctypes.c_voidp)

对于32位将是4,对于64位将是8。

Try using ctypes to get the size of a void pointer:

import ctypes
print ctypes.sizeof(ctypes.c_voidp)

It’ll be 4 for 32 bit or 8 for 64 bit.


回答 4

打开python控制台:

import platform
platform.architecture()[0]

它应根据您的平台显示“ 64bit”或“ 32bit”。

或者对于OS X二进制文件):

import sys
sys.maxsize > 2**32 
# it should display True in case of 64bit and False in case of 32bit

Open python console:

import platform
platform.architecture()[0]

it should display the ’64bit’ or ’32bit’ according to your platform.

Alternatively( in case of OS X binaries ):

import sys
sys.maxsize > 2**32 
# it should display True in case of 64bit and False in case of 32bit

回答 5

对于非编程解决方案,请查看活动监视器。它将64位进程的体系结构列为“ Intel(64位)”。

For a non-programmatic solution, look in the Activity Monitor. It lists the architecture of 64-bit processes as “Intel (64-bit)”.


回答 6

在我的Centos Linux系统上,我做了以下工作:

1)启动Python解释器(我使用的是2.6.6)
2)运行以下代码:

import platform
print(platform.architecture())

它给了我

(64bit, 'ELF')

On my Centos Linux system I did the following:

1) Started the Python interpreter (I’m using 2.6.6)
2) Ran the following code:

import platform
print(platform.architecture())

and it gave me

(64bit, 'ELF')

回答 7

platform.architecture() 笔记说:

注意:在Mac OS X(可能还有其他平台)上,可执行文件可能是包含多种体系结构的通用文件。

为了获得当前解释器的“ 64位”,查询sys.maxsize属性更加可靠:

import sys
is_64bits = sys.maxsize > 2**32

platform.architecture() notes say:

Note: On Mac OS X (and perhaps other platforms), executable files may be universal files containing multiple architectures.

To get at the “64-bitness” of the current interpreter, it is more reliable to query the sys.maxsize attribute:

import sys
is_64bits = sys.maxsize > 2**32

回答 8

分组一切…

考虑到:

  • 询问OSX的问题(我有一个旧的(且已破解的)VM,带有一个古老的Python版本)
  • 我的主要环境是Win
  • 我在Win上仅安装了32位版本(并且在Lnx上构建了一个“残缺的” 版本

我将使用Python 3Python 2在所有3个平台上进行示例。

  1. 检查[Python 3.Docs]:sys。maxsize值-与0x1000000002 ** 32)比较:对于64位,较大,对于32 ,较小:
    • OSX 9 x64
      • Python 2.7.10 x64
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 2.7.10 (default, Oct 14 2015, 05:51:29) \n[GCC 4.8.2] on darwin'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffffffffffff', True)
    • Ubuntu 16 x64
      • Python 3.5.2 x64
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.5.2 (default, Nov 23 2017, 16:37:01) \n[GCC 5.4.0 20160609] on linux'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffffffffffff', True)
      • Python 3.6.4 x86
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.6.4 (default, Apr 25 2018, 23:55:56) \n[GCC 5.4.0 20160609] on linux'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffff', False)
    • 赢10 x64
      • Python 3.5.4 x64
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffffffffffff', True)
      • Python 3.6.2 x86
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] on win32'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffff', False)


  1. 使用[Python 3.Docs]:结构。calcsizeformat确定由(指针)格式产生的对象大小。换句话说,确定指针大小(sizeof(void*)):
    • OSX 9 x64
      • Python 2.7.10 x64
        >>> import struct
        >>> struct.calcsize("P") * 8
        64
    • Ubuntu 16 x64
      • Python 3.5.2 x64
        >>> import struct
        >>> struct.calcsize("P") * 8
        64
      • Python 3.6.4 x86
        >>> import struct
        >>> struct.calcsize("P") * 8
        32
    • 赢10 x64
      • Python 3.5.4 x64
        >>> import struct
        >>> struct.calcsize("P") * 8
        64
      • Python 3.6.2 x86
        >>> import struct
        >>> struct.calcsize("P") * 8
        32


  1. 使用[Python 3.Docs]:ctypes-Python的外部函数库。它还归结为确定指针(sizeof(void*))的大小。注意,ctypes使用#2。(不一定要完成此任务),通过“ $ {PYTHON_SRC_DIR} / Lib / ctypes / __ init __。py”(在第15附近):
    • OSX 9 x64
      • Python 2.7.10 x64
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        64
    • Ubuntu 16 x64
      • Python 3.5.2 x64
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        64
      • Python 3.6.4 x86
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        32
    • 赢10 x64
      • Python 3.5.4 x64
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        64
      • Python 3.6.2 x86
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        32


  1. [Python 3.Docs]:平台。架构可执行文件= sys.executable,位=”,链接=” !!! 在OSX上不可靠!由于采用多体系结构可执行文件(或.dylib)格式(在某些情况下,使用#2。):
    • OSX 9 x64
      • Python 2.7.10 x64
        >>> import platform
        >>> platform.architecture()
        ('64bit', '')
    • Ubuntu 16 x64
      • Python 3.5.2 x64
        >>> import platform
        >>> platform.architecture()
        ('64bit', 'ELF')
      • Python 3.6.4 x86
        >>> import platform
        >>> platform.architecture()
        ('32bit', 'ELF')
    • 赢10 x64
      • Python 3.5.4 x64
        >>> import platform
        >>> platform.architecture()
        ('64bit', 'WindowsPE')
      • Python 3.6.2 x86
        >>> import platform
        >>> platform.architecture()
        ('32bit', 'WindowsPE')


  1. me脚的解决方法(gainarie)- 通过[Python 3.Docs]:os调用外部命令([man7]:FILE(1)系统命令#4的局限性适用(有时可能甚至无法使用):
    • OSX 9 x64
      • Python 2.7.10 x64
        >>> import os
        >>> os.system("file {0:s}".format(os.path.realpath(sys.executable)))
        /opt/OPSWbuildtools/2.0.6/bin/python2.7.global: Mach-O 64-bit executable x86_64
    • Ubuntu 16 x64
      • Python 3.5.2 x64
        >>> import os
        >>> os.system("file {0:s}".format(os.path.realpath(sys.executable)))
        /usr/bin/python3.5: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=59a8ef36ca241df24686952480966d7bc0d7c6ea, stripped
      • Python 3.6.4 x86
        >>> import os
        >>> os.system("file {0:s}".format(os.path.realpath(sys.executable)))
        /home/cfati/Work/Dev/Python-3.6.4/python: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=5c3d4eeadbd13cd91445d08f90722767b0747de2, not stripped
    • 赢10 x64
      • 文件工具不存在,还有其他第三方工具可以使用,但我不会坚持使用它们


具体

  1. 通过[Python 3.Docs]检查环境变量(例如%PROCESSOR_ARCHITECTURE%(或其他)):操作系统。环境
    • 赢10 x64
      • Python 3.5.4 x64
        >>> import os
        >>> os.environ["PROCESSOR_ARCHITECTURE"]
        'AMD64'
      • Python 3.6.2 x86
        >>> import os
        >>> os.environ["PROCESSOR_ARCHITECTURE"]
        'x86'


  1. [Python 3.Docs]:sys。版本(也显示在1条第一线启动解释时)
    • 检查#1。

Grouping everything…

Considering that:

  • The question is asked for OSX (I have an old (and cracked) VM with an ancient Python version)
  • My main env is Win
  • I only have the 32bit version installed on Win (and I built a “crippled” one on Lnx)

I’m going to exemplify on all 3 platforms, using Python 3 and Python 2.

  1. Check [Python 3.Docs]: sys.maxsize value – compare it to 0x100000000 (2 ** 32): greater for 64bit, smaller for 32bit:
    • OSX 9 x64:
      • Python 2.7.10 x64:
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 2.7.10 (default, Oct 14 2015, 05:51:29) \n[GCC 4.8.2] on darwin'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffffffffffff', True)
        
    • Ubuntu 16 x64:
      • Python 3.5.2 x64:
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.5.2 (default, Nov 23 2017, 16:37:01) \n[GCC 5.4.0 20160609] on linux'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffffffffffff', True)
        
      • Python 3.6.4 x86:
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.6.4 (default, Apr 25 2018, 23:55:56) \n[GCC 5.4.0 20160609] on linux'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffff', False)
        
    • Win 10 x64:
      • Python 3.5.4 x64:
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.5.4 (v3.5.4:3f56838, Aug  8 2017, 02:17:05) [MSC v.1900 64 bit (AMD64)] on win32'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffffffffffff', True)
        
      • Python 3.6.2 x86:
        >>> import sys
        >>> "Python {0:s} on {1:s}".format(sys.version, sys.platform)
        'Python 3.6.2 (v3.6.2:5fd33b5, Jul  8 2017, 04:14:34) [MSC v.1900 32 bit (Intel)] on win32'
        >>> hex(sys.maxsize), sys.maxsize > 0x100000000
        ('0x7fffffff', False)
        


  1. Use [Python 3.Docs]: struct.calcsize(format) to determine the object size produced by the (pointer) format. In other words, determines the pointer size (sizeof(void*)):
    • OSX 9 x64:
      • Python 2.7.10 x64:
        >>> import struct
        >>> struct.calcsize("P") * 8
        64
        
    • Ubuntu 16 x64:
      • Python 3.5.2 x64:
        >>> import struct
        >>> struct.calcsize("P") * 8
        64
        
      • Python 3.6.4 x86:
        >>> import struct
        >>> struct.calcsize("P") * 8
        32
        
    • Win 10 x64:
      • Python 3.5.4 x64:
        >>> import struct
        >>> struct.calcsize("P") * 8
        64
        
      • Python 3.6.2 x86:
        >>> import struct
        >>> struct.calcsize("P") * 8
        32
        


  1. Use [Python 3.Docs]: ctypes – A foreign function library for Python. It also boils down to determining the size of a pointer (sizeof(void*)). As a note, ctypes uses #2. (not necessarily for this task) via “${PYTHON_SRC_DIR}/Lib/ctypes/__init__.py” (around line #15):
    • OSX 9 x64:
      • Python 2.7.10 x64:
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        64
        
    • Ubuntu 16 x64:
      • Python 3.5.2 x64:
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        64
        
      • Python 3.6.4 x86:
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        32
        
    • Win 10 x64:
      • Python 3.5.4 x64:
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        64
        
      • Python 3.6.2 x86:
        >>> import ctypes
        >>> ctypes.sizeof(ctypes.c_void_p) * 8
        32
        


  1. [Python 3.Docs]: platform.architecture(executable=sys.executable, bits=”, linkage=”) !!! NOT reliable on OSX !!! due to multi arch executable (or .dylib) format (in some cases, uses #2.):
    • OSX 9 x64:
      • Python 2.7.10 x64:
        >>> import platform
        >>> platform.architecture()
        ('64bit', '')
        
    • Ubuntu 16 x64:
      • Python 3.5.2 x64:
        >>> import platform
        >>> platform.architecture()
        ('64bit', 'ELF')
        
      • Python 3.6.4 x86:
        >>> import platform
        >>> platform.architecture()
        ('32bit', 'ELF')
        
    • Win 10 x64:
      • Python 3.5.4 x64:
        >>> import platform
        >>> platform.architecture()
        ('64bit', 'WindowsPE')
        
      • Python 3.6.2 x86:
        >>> import platform
        >>> platform.architecture()
        ('32bit', 'WindowsPE')
        


  1. Lame workaround (gainarie) – invoke an external command ([man7]: FILE(1)) via [Python 3.Docs]: os.system(command). The limitations of #4. apply (sometimes it might not even work):
    • OSX 9 x64:
      • Python 2.7.10 x64:
        >>> import os
        >>> os.system("file {0:s}".format(os.path.realpath(sys.executable)))
        /opt/OPSWbuildtools/2.0.6/bin/python2.7.global: Mach-O 64-bit executable x86_64
        
    • Ubuntu 16 x64:
      • Python 3.5.2 x64:
        >>> import os
        >>> os.system("file {0:s}".format(os.path.realpath(sys.executable)))
        /usr/bin/python3.5: ELF 64-bit LSB executable, x86-64, version 1 (SYSV), dynamically linked, interpreter /lib64/ld-linux-x86-64.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=59a8ef36ca241df24686952480966d7bc0d7c6ea, stripped
        
      • Python 3.6.4 x86:
        >>> import os
        >>> os.system("file {0:s}".format(os.path.realpath(sys.executable)))
        /home/cfati/Work/Dev/Python-3.6.4/python: ELF 32-bit LSB executable, Intel 80386, version 1 (SYSV), dynamically linked, interpreter /lib/ld-linux.so.2, for GNU/Linux 2.6.32, BuildID[sha1]=5c3d4eeadbd13cd91445d08f90722767b0747de2, not stripped
        
    • Win 10 x64:
      • file utility is not present, there are other 3rd Party tools that can be used, but I’m not going to insist on them


Win specific:

  1. Check env vars (e.g. %PROCESSOR_ARCHITECTURE% (or others)) via [Python 3.Docs]: os.environ:
    • Win 10 x64:
      • Python 3.5.4 x64:
        >>> import os
        >>> os.environ["PROCESSOR_ARCHITECTURE"]
        'AMD64'
        
      • Python 3.6.2 x86:
        >>> import os
        >>> os.environ["PROCESSOR_ARCHITECTURE"]
        'x86'
        


  1. [Python 3.Docs]: sys.version (also displayed in the 1st line when starting the interpreter)
    • Check #1.

回答 9

struct.calcsize("P")返回存储单个指针所需的字节大小。在32位系统上,它将返回4个字节。在64位系统上,它将返回8个字节。

因此,32如果您运行的是32位python并且64运行的是64 位python,则会返回以下内容:

Python 2

import struct;print struct.calcsize("P") * 8

Python 3

import struct;print(struct.calcsize("P") * 8)

struct.calcsize("P") returns size of the bytes required to store a single pointer. On a 32-bit system, it would return 4 bytes. On a 64-bit system, it would return 8 bytes.

So the following would return 32 if you’re running 32-bit python and 64 if you’re running 64-bit python:

Python 2

import struct;print struct.calcsize("P") * 8

Python 3

import struct;print(struct.calcsize("P") * 8)

回答 10

python -VV在命令行中执行a 。它应该返回版本。

Do a python -VV in the command line. It should return the version.


回答 11

C:\Users\xyz>python

Python 2.7.6 (default, Nov XY ..., 19:24:24) **[MSC v.1500 64 bit (AMD64)] on win
32**
Type "help", "copyright", "credits" or "license" for more information.
>>>

在cmd中点击python后

C:\Users\xyz>python

Python 2.7.6 (default, Nov XY ..., 19:24:24) **[MSC v.1500 64 bit (AMD64)] on win
32**
Type "help", "copyright", "credits" or "license" for more information.
>>>

after hitting python in cmd


回答 12

import sys
print(sys.version)

3.5.1(v3.5.1:37a07cee5969,2015年12月6日,01:54:25)[MSC v.1900 64位(AMD64) ]

import sys
print(sys.version)

3.5.1 (v3.5.1:37a07cee5969, Dec 6 2015, 01:54:25) [MSC v.1900 64 bit (AMD64)]


回答 13

根据abe32的回答,

import sys
n_bits = 32 << bool(sys.maxsize >> 32)

n_bits将具有32或64位。

Based On abe32’s answer,

import sys
n_bits = 32 << bool(sys.maxsize >> 32)

n_bits will have 32 or 64 bits.


回答 14

对于32位,它将返回32,对于64位,它将返回64

import struct
print(struct.calcsize("P") * 8)

For 32 bit it will return 32 and for 64 bit it will return 64

import struct
print(struct.calcsize("P") * 8)

回答 15

平台架构不是可靠的方法。相反,我们:

$ arch -i386 /usr/local/bin/python2.7
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform, sys
>>> platform.architecture(), sys.maxsize
(('64bit', ''), 2147483647)
>>> ^D
$ arch -x86_64 /usr/local/bin/python2.7
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform, sys
>>> platform.architecture(), sys.maxsize
(('64bit', ''), 9223372036854775807)

Platform Architecture is not the reliable way. Instead us:

$ arch -i386 /usr/local/bin/python2.7
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform, sys
>>> platform.architecture(), sys.maxsize
(('64bit', ''), 2147483647)
>>> ^D
$ arch -x86_64 /usr/local/bin/python2.7
Python 2.7.9 (v2.7.9:648dcafa7e5f, Dec 10 2014, 10:10:46)
[GCC 4.2.1 (Apple Inc. build 5666) (dot 3)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> import platform, sys
>>> platform.architecture(), sys.maxsize
(('64bit', ''), 9223372036854775807)

回答 16

platform.architecture() 是有问题的(而且昂贵)。

sys.maxsize > 2**32从Py2.6开始方便地进行测试。

这是对实际(默认)指针大小的可靠测试,至少从Py2.3:开始兼容struct.calcsize('P') == 8。也:ctypes.sizeof(ctypes.c_void_p) == 8

注意:可以使用gcc选项构建-mx32,这是64位体系结构的应用程序,但是默认使用32位指针(节省内存和速度)。’sys.maxsize = ssize_t’可能不严格表示C指针大小(2**31 - 1无论如何通常如此)。而且,有些系统的代码和数据的指针大小不同,因此需要澄清辨别“ 32位或64位模式”的目的是什么?

platform.architecture() is problematic (and expensive).

Conveniently test for sys.maxsize > 2**32 since Py2.6 .

This is a reliable test for the actual (default) pointer size and compatible at least since Py2.3: struct.calcsize('P') == 8. Also: ctypes.sizeof(ctypes.c_void_p) == 8.

Notes: There can be builds with gcc option -mx32 or so, which are 64bit architecture applications, but use 32bit pointers as default (saving memory and speed). ‘sys.maxsize = ssize_t’ may not strictly represent the C pointer size (its usually 2**31 - 1 anyway). And there were/are systems which have different pointer sizes for code and data and it needs to be clarified what exactly is the purpose of discerning “32bit or 64bit mode?”


-1在numpy重塑中是什么意思?

问题:-1在numpy重塑中是什么意思?

可以使用参数为-1的整形函数将numpy矩阵整形为向量。但我不知道-1在这里意味着什么。

例如:

a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])
b = numpy.reshape(a, -1)

结果b是:matrix([[1, 2, 3, 4, 5, 6, 7, 8]])

有人知道-1在这里意味着什么吗?并且似乎python赋予-1几种含义,例如:array[-1]表示最后一个元素。你能解释一下吗?

A numpy matrix can be reshaped into a vector using reshape function with parameter -1. But I don’t know what -1 means here.

For example:

a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])
b = numpy.reshape(a, -1)

The result of b is: matrix([[1, 2, 3, 4, 5, 6, 7, 8]])

Does anyone know what -1 means here? And it seems python assign -1 several meanings, such as: array[-1] means the last element. Can you give an explanation?


回答 0

提供新形状所需满足的标准是“新形状应与原始形状兼容”

numpy允许我们将新形状参数之一设为-1(例如:(2,-1)或(-1,3),但不提供(-1,-1))。它只是意味着它是一个未知的维,我们希望numpy弄清楚。numpy将通过查看 “数组的长度和剩余维数”并确保满足上述条件来解决这个问题

现在看示例。

z = np.array([[1, 2, 3, 4],
         [5, 6, 7, 8],
         [9, 10, 11, 12]])
z.shape
(3, 4)

现在尝试用(-1)重塑形状。结果新形状为(12,)并与原始形状(3,4)兼容

z.reshape(-1)
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

现在尝试用(-1,1)重塑形状。我们将列设置为1,将行设置为unknown。因此我们得到的新形状为(12,1)。又与原始形状(3,4)兼容

z.reshape(-1,1)
array([[ 1],
   [ 2],
   [ 3],
   [ 4],
   [ 5],
   [ 6],
   [ 7],
   [ 8],
   [ 9],
   [10],
   [11],
   [12]])

以上与numpy建议/错误消息一致,reshape(-1,1)用于单个功能;即单列

array.reshape(-1, 1)如果数据具有单一功能,则使用来重塑数据

新形状为(-1,2)。未知行,第2列。我们得到的新形状为(6,2)

z.reshape(-1, 2)
array([[ 1,  2],
   [ 3,  4],
   [ 5,  6],
   [ 7,  8],
   [ 9, 10],
   [11, 12]])

现在尝试使列为未知。新形状为(1,-1)。即,行为1,列未知。我们得到的结果新形状为(1,12)

z.reshape(1,-1)
array([[ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]])

以上与numpy建议/错误消息一致,reshape(1,-1)用于单个示例;即单排

使用数据array.reshape(1, -1)是否包含单个样本来重塑数据

新形状(2,-1)。第2行,列不明。我们得到的结果新形状为(2,6)

z.reshape(2, -1)
array([[ 1,  2,  3,  4,  5,  6],
   [ 7,  8,  9, 10, 11, 12]])

新形状为(3,-1)。第3行,列不明。我们得到的结果新形状为(3,4)

z.reshape(3, -1)
array([[ 1,  2,  3,  4],
   [ 5,  6,  7,  8],
   [ 9, 10, 11, 12]])

最后,如果我们尝试提供两个未知尺寸,即新形状为(-1,-1)。会抛出错误

z.reshape(-1, -1)
ValueError: can only specify one unknown dimension

The criterion to satisfy for providing the new shape is that ‘The new shape should be compatible with the original shape’

numpy allow us to give one of new shape parameter as -1 (eg: (2,-1) or (-1,3) but not (-1, -1)). It simply means that it is an unknown dimension and we want numpy to figure it out. And numpy will figure this by looking at the ‘length of the array and remaining dimensions’ and making sure it satisfies the above mentioned criteria

Now see the example.

z = np.array([[1, 2, 3, 4],
         [5, 6, 7, 8],
         [9, 10, 11, 12]])
z.shape
(3, 4)

Now trying to reshape with (-1) . Result new shape is (12,) and is compatible with original shape (3,4)

z.reshape(-1)
array([ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12])

Now trying to reshape with (-1, 1) . We have provided column as 1 but rows as unknown . So we get result new shape as (12, 1).again compatible with original shape(3,4)

z.reshape(-1,1)
array([[ 1],
   [ 2],
   [ 3],
   [ 4],
   [ 5],
   [ 6],
   [ 7],
   [ 8],
   [ 9],
   [10],
   [11],
   [12]])

The above is consistent with numpy advice/error message, to use reshape(-1,1) for a single feature; i.e. single column

Reshape your data using array.reshape(-1, 1) if your data has a single feature

New shape as (-1, 2). row unknown, column 2. we get result new shape as (6, 2)

z.reshape(-1, 2)
array([[ 1,  2],
   [ 3,  4],
   [ 5,  6],
   [ 7,  8],
   [ 9, 10],
   [11, 12]])

Now trying to keep column as unknown. New shape as (1,-1). i.e, row is 1, column unknown. we get result new shape as (1, 12)

z.reshape(1,-1)
array([[ 1,  2,  3,  4,  5,  6,  7,  8,  9, 10, 11, 12]])

The above is consistent with numpy advice/error message, to use reshape(1,-1) for a single sample; i.e. single row

Reshape your data using array.reshape(1, -1) if it contains a single sample

New shape (2, -1). Row 2, column unknown. we get result new shape as (2,6)

z.reshape(2, -1)
array([[ 1,  2,  3,  4,  5,  6],
   [ 7,  8,  9, 10, 11, 12]])

New shape as (3, -1). Row 3, column unknown. we get result new shape as (3,4)

z.reshape(3, -1)
array([[ 1,  2,  3,  4],
   [ 5,  6,  7,  8],
   [ 9, 10, 11, 12]])

And finally, if we try to provide both dimension as unknown i.e new shape as (-1,-1). It will throw an error

z.reshape(-1, -1)
ValueError: can only specify one unknown dimension

回答 1

用于整形数组。

假设我们有一个尺寸为2 x 10 x 10的3维数组:

r = numpy.random.rand(2, 10, 10) 

现在我们要重塑为5 X 5 x 8:

numpy.reshape(r, shape=(5, 5, 8)) 

会做的工作。

请注意,一旦固定了第一个dim = 5和第二个dim = 5,就不需要确定第三维。为了帮助您懒惰,python提供了-1选项:

numpy.reshape(r, shape=(5, 5, -1)) 

将为您提供形状=(5,5,8)的数组。

同样

numpy.reshape(r, shape=(50, -1)) 

将为您提供形状=(50,4)的数组

您可以在http://anie.me/numpy-reshape-transpose-theano-dimshuffle/了解更多信息

Used to reshape an array.

Say we have a 3 dimensional array of dimensions 2 x 10 x 10:

r = numpy.random.rand(2, 10, 10) 

Now we want to reshape to 5 X 5 x 8:

numpy.reshape(r, shape=(5, 5, 8)) 

will do the job.

Note that, once you fix first dim = 5 and second dim = 5, you don’t need to determine third dimension. To assist your laziness, python gives the option of -1:

numpy.reshape(r, shape=(5, 5, -1)) 

will give you an array of shape = (5, 5, 8).

Likewise,

numpy.reshape(r, shape=(50, -1)) 

will give you an array of shape = (50, 4)

You can read more at http://anie.me/numpy-reshape-transpose-theano-dimshuffle/


回答 2

根据the documentation

newshape:int或int的元组

新形状应与原始形状兼容。如果是整数,则结果将是该长度的一维数组。一个形状尺寸可以为-1。在这种情况下,该值是根据数组的长度和其余维来推断的。

According to the documentation:

newshape : int or tuple of ints

The new shape should be compatible with the original shape. If an integer, then the result will be a 1-D array of that length. One shape dimension can be -1. In this case, the value is inferred from the length of the array and remaining dimensions.


回答 3

numpy.reshape(a,newshape,order {})检查以下链接以获取更多信息。 https://docs.scipy.org/doc/numpy/reference/generation/numpy.reshape.html

对于以下示例,您提到的输出将结果向量解释为单行。(-1)表示行数为1。

a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])
b = numpy.reshape(a, -1)

输出:

矩阵([[1、2、3、4、5、6、7、8]])

这可以用另一个示例更精确地解释:

b = np.arange(10).reshape((-1,1))

输出:(是一维列式数组)

数组([[0],

   [1],
   [2],
   [3],
   [4],
   [5],
   [6],
   [7],
   [8],
   [9]])

b = np.arange(10).reshape((1,-1))

输出:(是一维行数组)

数组([[0,1,2,3,4,5,6,7,8,9]])

numpy.reshape(a,newshape,order{}) check the below link for more info. https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html

for the below example you mentioned the output explains the resultant vector to be a single row.(-1) indicates the number of rows to be 1. if the

a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])
b = numpy.reshape(a, -1)

output:

matrix([[1, 2, 3, 4, 5, 6, 7, 8]])

this can be explained more precisely with another example:

b = np.arange(10).reshape((-1,1))

output:(is a 1 dimensional columnar array)

array([[0],

   [1],
   [2],
   [3],
   [4],
   [5],
   [6],
   [7],
   [8],
   [9]])

b = np.arange(10).reshape((1,-1))

output:(is a 1 dimensional row array)

array([[0, 1, 2, 3, 4, 5, 6, 7, 8, 9]])


回答 4

这很容易理解。“ -1”代表“未知尺寸”,可以从另一个尺寸推断出来。在这种情况下,如果您这样设置矩阵:

a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])

像这样修改矩阵:

b = numpy.reshape(a, -1)

它将对矩阵a调用一些默认操作,这将返回1-d numpy数组/矩阵。

但是,我认为使用这样的代码不是一个好主意。为什么不尝试:

b = a.reshape(1,-1)

它将为您提供相同的结果,并使读者更清楚地理解:将b设置为a的另一种形状。对于a,我们没有多少列(将其设置为-1!),但是我们想要一维数组(将第一个参数设置为1!)。

It is fairly easy to understand. The “-1” stands for “unknown dimension” which can should be infered from another dimension. In this case, if you set your matrix like this:

a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])

Modify your matrix like this:

b = numpy.reshape(a, -1)

It will call some deafult operations to the matrix a, which will return a 1-d numpy array/martrix.

However, I don’t think it is a good idea to use code like this. Why not try:

b = a.reshape(1,-1)

It will give you the same result and it’s more clear for readers to understand: Set b as another shape of a. For a, we don’t how much columns it should have(set it to -1!), but we want a 1-dimension array(set the first parameter to 1!).


回答 5

长话短说:您设置了一些尺寸,然后让NumPy设置了其余的尺寸。

(userDim1, userDim2, ..., -1) -->>

(userDim1, userDim1, ..., TOTAL_DIMENSION - (userDim1 + userDim2 + ...))

Long story short: you set some dimensions and let NumPy set the remaining(s).

(userDim1, userDim2, ..., -1) -->>

(userDim1, userDim1, ..., TOTAL_DIMENSION - (userDim1 + userDim2 + ...))

回答 6

这只是意味着您不确定可以提供多少行或列,而您正在让numpy建议要重整的列数或行数。

numpy提供了-1 https://docs.scipy.org/doc/numpy/reference/genic/numpy.reshape.html的最后一个示例

检查下面的代码及其输出以更好地了解(-1):

码:-

import numpy
a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])
print("Without reshaping  -> ")
print(a)
b = numpy.reshape(a, -1)
print("HERE We don't know about what number we should give to row/col")
print("Reshaping as (a,-1)")
print(b)
c = numpy.reshape(a, (-1,2))
print("HERE We just know about number of columns")
print("Reshaping as (a,(-1,2))")
print(c)
d = numpy.reshape(a, (2,-1))
print("HERE We just know about number of rows")
print("Reshaping as (a,(2,-1))")
print(d)

输出:-

Without reshaping  -> 
[[1 2 3 4]
 [5 6 7 8]]
HERE We don't know about what number we should give to row/col
Reshaping as (a,-1)
[[1 2 3 4 5 6 7 8]]
HERE We just know about number of columns
Reshaping as (a,(-1,2))
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
HERE We just know about number of rows
Reshaping as (a,(2,-1))
[[1 2 3 4]
 [5 6 7 8]]

It simply means that you are not sure about what number of rows or columns you can give and you are asking numpy to suggest number of column or rows to get reshaped in.

numpy provides last example for -1 https://docs.scipy.org/doc/numpy/reference/generated/numpy.reshape.html

check below code and its output to better understand about (-1):

CODE:-

import numpy
a = numpy.matrix([[1, 2, 3, 4], [5, 6, 7, 8]])
print("Without reshaping  -> ")
print(a)
b = numpy.reshape(a, -1)
print("HERE We don't know about what number we should give to row/col")
print("Reshaping as (a,-1)")
print(b)
c = numpy.reshape(a, (-1,2))
print("HERE We just know about number of columns")
print("Reshaping as (a,(-1,2))")
print(c)
d = numpy.reshape(a, (2,-1))
print("HERE We just know about number of rows")
print("Reshaping as (a,(2,-1))")
print(d)

OUTPUT :-

Without reshaping  -> 
[[1 2 3 4]
 [5 6 7 8]]
HERE We don't know about what number we should give to row/col
Reshaping as (a,-1)
[[1 2 3 4 5 6 7 8]]
HERE We just know about number of columns
Reshaping as (a,(-1,2))
[[1 2]
 [3 4]
 [5 6]
 [7 8]]
HERE We just know about number of rows
Reshaping as (a,(2,-1))
[[1 2 3 4]
 [5 6 7 8]]

回答 7

import numpy as np
x = np.array([[2,3,4], [5,6,7]]) 

# Convert any shape to 1D shape
x = np.reshape(x, (-1)) # Making it 1 row -> (6,)

# When you don't care about rows and just want to fix number of columns
x = np.reshape(x, (-1, 1)) # Making it 1 column -> (6, 1)
x = np.reshape(x, (-1, 2)) # Making it 2 column -> (3, 2)
x = np.reshape(x, (-1, 3)) # Making it 3 column -> (2, 3)

# When you don't care about columns and just want to fix number of rows
x = np.reshape(x, (1, -1)) # Making it 1 row -> (1, 6)
x = np.reshape(x, (2, -1)) # Making it 2 row -> (2, 3)
x = np.reshape(x, (3, -1)) # Making it 3 row -> (3, 2)
import numpy as np
x = np.array([[2,3,4], [5,6,7]]) 

# Convert any shape to 1D shape
x = np.reshape(x, (-1)) # Making it 1 row -> (6,)

# When you don't care about rows and just want to fix number of columns
x = np.reshape(x, (-1, 1)) # Making it 1 column -> (6, 1)
x = np.reshape(x, (-1, 2)) # Making it 2 column -> (3, 2)
x = np.reshape(x, (-1, 3)) # Making it 3 column -> (2, 3)

# When you don't care about columns and just want to fix number of rows
x = np.reshape(x, (1, -1)) # Making it 1 row -> (1, 6)
x = np.reshape(x, (2, -1)) # Making it 2 row -> (2, 3)
x = np.reshape(x, (3, -1)) # Making it 3 row -> (3, 2)

回答 8

转换的最终结果是,最终数组中的元素数量与初始数组或数据帧的元素数量相同。

-1对应于行或列的未知计数。我们可以将其视为x(未知)。x通过将原始数组中元素的数量除以有序对的其他值-1而获得。

例子

具有reshape(-1,1)的12个元素对应于x= 12/1 = 12行和1列的数组。


具有reshape(1,-1)的12个元素对应于具有1行x= 12/1 = 12列的数组。

The final outcome of the conversion is that the number of elements in the final array is same as that of the initial array or data frame.

-1 corresponds to the unknown count of the row or column. we can think of it as x(unknown). x is obtained by dividing the umber of elements in the original array by the other value of the ordered pair with -1.

Examples

12 elements with reshape(-1,1) corresponds to an array with x=12/1=12 rows and 1 column.


12 elements with reshape(1,-1) corresponds to an array with 1 row and x=12/1=12 columns.


如何禁用python警告

问题:如何禁用python警告

我正在使用的代码会使用该warnings库抛出很多(目前对我来说)无用的警告。阅读(/扫描)文档后,我只找到了一种禁用单个功能警告的方法。但是我不想更改太多代码。

可能有像这样的标志python -no-warning foo.py吗?

你会推荐什么?

I am working with code that throws a lot of (for me at the moment) useless warnings using the warnings library. Reading (/scanning) the documentation I only found a way to disable warnings for single functions. But I don’t want to change so much of the code.

Is there maybe a flag like python -no-warning foo.py?

What would you recommend?


回答 0

-W选项

python -W ignore foo.py

There’s the -W option.

python -W ignore foo.py


回答 1

您是否查看了python文档的“ 抑制警告”部分?

如果您使用的代码知道会发出警告(例如已弃用的函数),但又不想看到该警告,则可以使用catch_warnings上下文管理器来抑制该警告:

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

我不容忍,但是您可以通过以下方式取消所有警告

import warnings
warnings.filterwarnings("ignore")

例如:

>>> import warnings
>>> def f():
...  print('before')
...  warnings.warn('you are warned!')
...  print('after')
>>> f()
before
__main__:3: UserWarning: you are warned!
after
>>> warnings.filterwarnings("ignore")
>>> f()
before
after

Did you look at the suppress warnings section of the python docs?

If you are using code that you know will raise a warning, such as a deprecated function, but do not want to see the warning, then it is possible to suppress the warning using the catch_warnings context manager:

import warnings

def fxn():
    warnings.warn("deprecated", DeprecationWarning)

with warnings.catch_warnings():
    warnings.simplefilter("ignore")
    fxn()

I don’t condone it, but you could just suppress all warnings with this:

import warnings
warnings.filterwarnings("ignore")

Ex:

>>> import warnings
>>> def f():
...  print('before')
...  warnings.warn('you are warned!')
...  print('after')
>>> f()
before
__main__:3: UserWarning: you are warned!
after
>>> warnings.filterwarnings("ignore")
>>> f()
before
after

回答 2

您还可以定义环境变量(2010年的新功能-即python 2.7)

export PYTHONWARNINGS="ignore"

像这样测试:默认

$ export PYTHONWARNINGS="default"
$ python
>>> import warnings
>>> warnings.warn('my warning')
__main__:1: UserWarning: my warning
>>>

忽略警告

$ export PYTHONWARNINGS="ignore"
$ python
>>> import warnings
>>> warnings.warn('my warning')
>>> 

对于弃用警告,请查看如何忽略python中的弃用警告

在这里复制…

warnings模块的文档中:

 #!/usr/bin/env python -W ignore::DeprecationWarning

如果您使用的是Windows,请-W ignore::DeprecationWarning作为参数传递给Python。最好通过强制转换为int来解决问题。

(请注意,在Python 3.2中,默认情况下会忽略弃用警告。)

要么:

import warnings

with warnings.catch_warnings():
    warnings.filterwarnings("ignore", category=DeprecationWarning)
    import md5, sha

yourcode()

现在您仍然得到所有其他DeprecationWarnings,但不是由以下原因引起的:

import md5, sha

You can also define an environment variable (new feature in 2010 – i.e. python 2.7)

export PYTHONWARNINGS="ignore"

Test like this: Default

$ export PYTHONWARNINGS="default"
$ python
>>> import warnings
>>> warnings.warn('my warning')
__main__:1: UserWarning: my warning
>>>

Ignore warnings

$ export PYTHONWARNINGS="ignore"
$ python
>>> import warnings
>>> warnings.warn('my warning')
>>> 

For deprecation warnings have a look at how-to-ignore-deprecation-warnings-in-python

Copied here…

From documentation of the warnings module:

 #!/usr/bin/env python -W ignore::DeprecationWarning

If you’re on Windows: pass -W ignore::DeprecationWarning as an argument to Python. Better though to resolve the issue, by casting to int.

(Note that in Python 3.2, deprecation warnings are ignored by default.)

Or:

import warnings

with warnings.catch_warnings():
    warnings.filterwarnings("ignore", category=DeprecationWarning)
    import md5, sha

yourcode()

Now you still get all the other DeprecationWarnings, but not the ones caused by:

import md5, sha

回答 3

这是一个老问题,但是PEP 565中有一些较新的指南,如果您正在编写python应用程序,则应关闭所有警告,请使用:

import sys
import warnings

if not sys.warnoptions:
    warnings.simplefilter("ignore")

推荐这样做的原因是默认情况下它会关闭所有警告,但至关重要的是允许通过python -W命令行或再次将其打开PYTHONWARNINGS

This is an old question but there is some newer guidance in PEP 565 that to turn off all warnings if you’re writing a python application you should use:

import sys
import warnings

if not sys.warnoptions:
    warnings.simplefilter("ignore")

The reason this is recommended is that it turns off all warnings by default but crucially allows them to be switched back on via python -W on the command line or PYTHONWARNINGS.


回答 4

如果您不想要复杂的东西,那么:

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

If you don’t want something complicated, then:

import warnings
warnings.filterwarnings("ignore", category=FutureWarning)

回答 5

如果您知道通常会遇到什么无用的警告,则可以按消息过滤它们。

import warnings

#ignore by message
warnings.filterwarnings("ignore", message="divide by zero encountered in divide")

#part of the message is also okay
warnings.filterwarnings("ignore", message="divide by zero encountered") 
warnings.filterwarnings("ignore", message="invalid value encountered")

If you know what are the useless warnings you usually encounter, you can filter them by message.

import warnings

#ignore by message
warnings.filterwarnings("ignore", message="divide by zero encountered in divide")

#part of the message is also okay
warnings.filterwarnings("ignore", message="divide by zero encountered") 
warnings.filterwarnings("ignore", message="invalid value encountered")

回答 6

我意识到这仅适用于特定情况,但是在numpy上下文中我真的很喜欢使用np.errstate

np.sqrt(-1)
__main__:1: RuntimeWarning: invalid value encountered in sqrt
nan

但是,使用np.errstate

with np.errstate(invalid='ignore'):
    np.sqrt(-1)
nan

最好的部分是您可以将其仅应用于非常特定的代码行。

I realise this is only applicable to a niche of the situations, but within a numpy context I really like using np.errstate:

np.sqrt(-1)
__main__:1: RuntimeWarning: invalid value encountered in sqrt
nan

However, using np.errstate:

with np.errstate(invalid='ignore'):
    np.sqrt(-1)
nan

The best part being you can apply this to very specific lines of code only.


回答 7

警告通过stderr输出,简单的解决方案是将’2> / dev / null’附加到CLI。对于许多用户来说,这很有意义,例如那些使用python 2.6依赖项(例如yum)的centos 6的用户,并且各种模块都被推到了灭绝的边缘。

对于涉及SNI等的密码学尤其如此。一个人可以使用以下过程中的proc更新2.6以进行HTTPS处理:https : //urllib3.readthedocs.io/en/latest/user-guide.html#ssl-py2

警告仍然存在,但是您想要的所有内容都已反向移植。尽管stdout内容本身不会更改,但stderr的重定向将使您获得干净的终端/外壳输出。

回应FriendFX。句子(1)用通用解决方案直接回答了这个问题。句子二(2)考虑到了python 2.6特定的引用的anchor re“ disable warnings”,并指出RHEL / centos 6用户不能直接使用2.6。尽管未引用任何具体的警告,但第二(2)款回答了我最经常得到的2.6问题,即密码模块中的缺点以及如何“现代化”(即升级,反向移植,修复)python的HTTPS / TLS性能。第三(3)段仅说明使用重定向和升级模块/依赖项的结果。

warnings are output via stderr and the simple solution is to append ‘2> /dev/null’ to the CLI. this makes a lot of sense to many users such as those with centos 6 that are stuck with python 2.6 dependencies (like yum) and various modules are being pushed to the edge of extinction in their coverage.

this is especially true for cryptography involving SNI et cetera. one can update 2.6 for HTTPS handling using the proc at: https://urllib3.readthedocs.io/en/latest/user-guide.html#ssl-py2

the warning is still in place, but everything you want is back-ported. the re-direct of stderr will leave you with clean terminal/shell output although the stdout content itself does not change.

responding to FriendFX. sentence one (1) responds directly to the problem with an universal solution. sentence two (2) takes into account the cited anchor re ‘disable warnings’ which is python 2.6 specific and notes that RHEL/centos 6 users cannot directly do without 2.6. although no specific warnings were cited, para two (2) answers the 2.6 question I most frequently get re the short-comings in the cryptography module and how one can “modernize” (i.e., upgrade, backport, fix) python’s HTTPS/TLS performance. para three (3) merely explains the outcome of using the re-direct and upgrading the module/dependencies.


尝试/使用Python请求模块的正确方法?

问题:尝试/使用Python请求模块的正确方法?

try:
    r = requests.get(url, params={'s': thing})
except requests.ConnectionError, e:
    print e #should I also sys.exit(1) after this?

它是否正确?有没有更好的方法来构造它?这会覆盖我所有的基地吗?

try:
    r = requests.get(url, params={'s': thing})
except requests.ConnectionError, e:
    print e #should I also sys.exit(1) after this?

Is this correct? Is there a better way to structure this? Will this cover all my bases?


回答 0

看一下Requests 异常文档。简而言之:

如果出现网络问题(例如DNS故障,连接被拒绝等),请求将引发ConnectionError异常。

如果发生罕见的无效HTTP响应,则请求将引发HTTPError异常。

如果请求超时,Timeout则会引发异常。

如果请求超过配置的最大重定向数,TooManyRedirects则会引发异常。

请求显式引发的所有异常都继承自requests.exceptions.RequestException

要回答您的问题,您显示的内容不会涵盖所有基础。您将只捕获与连接有关的错误,而不是超时的错误。

捕获异常时该做什么实际上取决于脚本/程序的设计。退出是否可以接受?您可以再试一次吗?如果错误是灾难性的,并且您无法继续进行,那么可以,您可以通过引发SystemExit(一种打印错误并调用的好方法)来中止程序sys.exit

您可以捕获基类异常,该异常将处理所有情况:

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.RequestException as e:  # This is the correct syntax
    raise SystemExit(e)

或者,您可以分别捕获它们并执行不同的操作。

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.Timeout:
    # Maybe set up for a retry, or continue in a retry loop
except requests.exceptions.TooManyRedirects:
    # Tell the user their URL was bad and try a different one
except requests.exceptions.RequestException as e:
    # catastrophic error. bail.
    raise SystemExit(e)

正如克里斯蒂安指出:

如果您希望http错误(例如401未经授权)引发异常,可以调用Response.raise_for_statusHTTPError如果响应是http错误,则将引发。

一个例子:

try:
    r = requests.get('http://www.google.com/nothere')
    r.raise_for_status()
except requests.exceptions.HTTPError as err:
    raise SystemExit(err)

将打印:

404 Client Error: Not Found for url: http://www.google.com/nothere

Have a look at the Requests exception docs. In short:

In the event of a network problem (e.g. DNS failure, refused connection, etc), Requests will raise a ConnectionError exception.

In the event of the rare invalid HTTP response, Requests will raise an HTTPError exception.

If a request times out, a Timeout exception is raised.

If a request exceeds the configured number of maximum redirections, a TooManyRedirects exception is raised.

All exceptions that Requests explicitly raises inherit from requests.exceptions.RequestException.

To answer your question, what you show will not cover all of your bases. You’ll only catch connection-related errors, not ones that time out.

What to do when you catch the exception is really up to the design of your script/program. Is it acceptable to exit? Can you go on and try again? If the error is catastrophic and you can’t go on, then yes, you may abort your program by raising SystemExit (a nice way to both print an error and call sys.exit).

You can either catch the base-class exception, which will handle all cases:

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.RequestException as e:  # This is the correct syntax
    raise SystemExit(e)

Or you can catch them separately and do different things.

try:
    r = requests.get(url, params={'s': thing})
except requests.exceptions.Timeout:
    # Maybe set up for a retry, or continue in a retry loop
except requests.exceptions.TooManyRedirects:
    # Tell the user their URL was bad and try a different one
except requests.exceptions.RequestException as e:
    # catastrophic error. bail.
    raise SystemExit(e)

As Christian pointed out:

If you want http errors (e.g. 401 Unauthorized) to raise exceptions, you can call Response.raise_for_status. That will raise an HTTPError, if the response was an http error.

An example:

try:
    r = requests.get('http://www.google.com/nothere')
    r.raise_for_status()
except requests.exceptions.HTTPError as err:
    raise SystemExit(err)

Will print:

404 Client Error: Not Found for url: http://www.google.com/nothere

回答 1

另一项建议是明确的。似乎最好是从特定错误到一般错误,以获取所需的错误来捕获,因此特定错误不会被一般错误掩盖。

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)

Http Error: 404 Client Error: Not Found for url: http://www.google.com/blahblah

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)     

OOps: Something Else 404 Client Error: Not Found for url: http://www.google.com/blahblah

One additional suggestion to be explicit. It seems best to go from specific to general down the stack of errors to get the desired error to be caught, so the specific ones don’t get masked by the general one.

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)

Http Error: 404 Client Error: Not Found for url: http://www.google.com/blahblah

vs

url='http://www.google.com/blahblah'

try:
    r = requests.get(url,timeout=3)
    r.raise_for_status()
except requests.exceptions.RequestException as err:
    print ("OOps: Something Else",err)
except requests.exceptions.HTTPError as errh:
    print ("Http Error:",errh)
except requests.exceptions.ConnectionError as errc:
    print ("Error Connecting:",errc)
except requests.exceptions.Timeout as errt:
    print ("Timeout Error:",errt)     

OOps: Something Else 404 Client Error: Not Found for url: http://www.google.com/blahblah

回答 2

异常对象还包含原始响应e.response,如果需要查看服务器响应中的错误正文,该对象可能很有用。例如:

try:
    r = requests.post('somerestapi.com/post-here', data={'birthday': '9/9/3999'})
    r.raise_for_status()
except requests.exceptions.HTTPError as e:
    print (e.response.text)

Exception object also contains original response e.response, that could be useful if need to see error body in response from the server. For example:

try:
    r = requests.post('somerestapi.com/post-here', data={'birthday': '9/9/3999'})
    r.raise_for_status()
except requests.exceptions.HTTPError as e:
    print (e.response.text)

python“ with”语句的目的是什么?

问题:python“ with”语句的目的是什么?

with今天是第一次遇到Python 语句。我已经使用Python几个月了,甚至不知道它的存在!考虑到它的地位有些晦涩,我认为值得一问:

  1. Python with语句旨在用于什么?
  2. 你用它来做什么?
  3. 我需要了解任何陷阱,还是与其使用相关的常见反模式?有什么try..finally比这更好用的情况with吗?
  4. 为什么没有更广泛地使用它?
  5. 哪些标准库类与之兼容?

I came across the Python with statement for the first time today. I’ve been using Python lightly for several months and didn’t even know of its existence! Given its somewhat obscure status, I thought it would be worth asking:

  1. What is the Python with statement designed to be used for?
  2. What do you use it for?
  3. Are there any gotchas I need to be aware of, or common anti-patterns associated with its use? Any cases where it is better use try..finally than with?
  4. Why isn’t it used more widely?
  5. Which standard library classes are compatible with it?

回答 0

  1. 我相信这已经被我之前的其他用户回答了,所以我仅出于完整性的考虑添加该with语句:该语句通过将常见的准备和清理任务封装在所谓的上下文管理器中来简化异常处理。可以在PEP 343中找到更多详细信息。例如,该open语句本身就是一个上下文管理器,它使您可以打开文件,只要with在使用它的语句上下文中执行该文件,就可以保持打开状态,并在离开上下文后立即将其关闭,无论您是由于异常还是在常规控制流程中离开了它。with因此,可以使用类似于C ++中的RAII模式的方式使用该语句:with语句并在您离开with上下文时释放。

  2. 一些示例是:使用打开文件,使用with open(filename) as fp:获取锁with lock:(在lock的实例threading.Lock)。您还可以使用中的contextmanager装饰器来构造自己的上下文管理器contextlib。例如,当我不得不临时更改当前目录然后返回到原来的位置时,我经常使用它:

    from contextlib import contextmanager
    import os
    
    @contextmanager
    def working_directory(path):
        current_dir = os.getcwd()
        os.chdir(path)
        try:
            yield
        finally:
            os.chdir(current_dir)
    
    with working_directory("data/stuff"):
        # do something within data/stuff
    # here I am back again in the original working directory
    

    这是另一个示例,该示例临时重定向sys.stdinsys.stdout并重定向sys.stderr到其他文件句柄并稍后将其还原:

    from contextlib import contextmanager
    import sys
    
    @contextmanager
    def redirected(**kwds):
        stream_names = ["stdin", "stdout", "stderr"]
        old_streams = {}
        try:
            for sname in stream_names:
                stream = kwds.get(sname, None)
                if stream is not None and stream != getattr(sys, sname):
                    old_streams[sname] = getattr(sys, sname)
                    setattr(sys, sname, stream)
            yield
        finally:
            for sname, stream in old_streams.iteritems():
                setattr(sys, sname, stream)
    
    with redirected(stdout=open("/tmp/log.txt", "w")):
         # these print statements will go to /tmp/log.txt
         print "Test entry 1"
         print "Test entry 2"
    # back to the normal stdout
    print "Back to normal stdout again"
    

    最后,另一个示例创建一个临时文件夹并在离开上下文时清理它:

    from tempfile import mkdtemp
    from shutil import rmtree
    
    @contextmanager
    def temporary_dir(*args, **kwds):
        name = mkdtemp(*args, **kwds)
        try:
            yield name
        finally:
            shutil.rmtree(name)
    
    with temporary_dir() as dirname:
        # do whatever you want
    
  1. I believe this has already been answered by other users before me, so I only add it for the sake of completeness: the with statement simplifies exception handling by encapsulating common preparation and cleanup tasks in so-called context managers. More details can be found in PEP 343. For instance, the open statement is a context manager in itself, which lets you open a file, keep it open as long as the execution is in the context of the with statement where you used it, and close it as soon as you leave the context, no matter whether you have left it because of an exception or during regular control flow. The with statement can thus be used in ways similar to the RAII pattern in C++: some resource is acquired by the with statement and released when you leave the with context.

  2. Some examples are: opening files using with open(filename) as fp:, acquiring locks using with lock: (where lock is an instance of threading.Lock). You can also construct your own context managers using the contextmanager decorator from contextlib. For instance, I often use this when I have to change the current directory temporarily and then return to where I was:

    from contextlib import contextmanager
    import os
    
    @contextmanager
    def working_directory(path):
        current_dir = os.getcwd()
        os.chdir(path)
        try:
            yield
        finally:
            os.chdir(current_dir)
    
    with working_directory("data/stuff"):
        # do something within data/stuff
    # here I am back again in the original working directory
    

    Here’s another example that temporarily redirects sys.stdin, sys.stdout and sys.stderr to some other file handle and restores them later:

    from contextlib import contextmanager
    import sys
    
    @contextmanager
    def redirected(**kwds):
        stream_names = ["stdin", "stdout", "stderr"]
        old_streams = {}
        try:
            for sname in stream_names:
                stream = kwds.get(sname, None)
                if stream is not None and stream != getattr(sys, sname):
                    old_streams[sname] = getattr(sys, sname)
                    setattr(sys, sname, stream)
            yield
        finally:
            for sname, stream in old_streams.iteritems():
                setattr(sys, sname, stream)
    
    with redirected(stdout=open("/tmp/log.txt", "w")):
         # these print statements will go to /tmp/log.txt
         print "Test entry 1"
         print "Test entry 2"
    # back to the normal stdout
    print "Back to normal stdout again"
    

    And finally, another example that creates a temporary folder and cleans it up when leaving the context:

    from tempfile import mkdtemp
    from shutil import rmtree
    
    @contextmanager
    def temporary_dir(*args, **kwds):
        name = mkdtemp(*args, **kwds)
        try:
            yield name
        finally:
            shutil.rmtree(name)
    
    with temporary_dir() as dirname:
        # do whatever you want
    

回答 1

我会建议两个有趣的讲座:

  • PEP 343 “ with”声明
  • Effbot了解Python的“ with”语句

1.with语句用于使用上下文管理器定义的方法来包装块的执行。这允许将常用try...except...finally用法模式封装起来,以方便重用。

2. 您可以执行以下操作:

with open("foo.txt") as foo_file:
    data = foo_file.read()

要么

from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
   do_something()

或(Python 3.1)

with open('data') as input_file, open('result', 'w') as output_file:
   for line in input_file:
     output_file.write(parse(line))

要么

lock = threading.Lock()
with lock:
    # Critical section of code

3. 我在这里看不到任何反模式。
引用Dive进入Python

试试..最终是好的。与更好。

4. 我想这与程序员使用try..catch..finally其他语言的语句的习惯有关。

I would suggest two interesting lectures:

  • PEP 343 The “with” Statement
  • Effbot Understanding Python’s “with” statement

1. The with statement is used to wrap the execution of a block with methods defined by a context manager. This allows common try...except...finally usage patterns to be encapsulated for convenient reuse.

2. You could do something like:

with open("foo.txt") as foo_file:
    data = foo_file.read()

OR

from contextlib import nested
with nested(A(), B(), C()) as (X, Y, Z):
   do_something()

OR (Python 3.1)

with open('data') as input_file, open('result', 'w') as output_file:
   for line in input_file:
     output_file.write(parse(line))

OR

lock = threading.Lock()
with lock:
    # Critical section of code

3. I don’t see any Antipattern here.
Quoting Dive into Python:

try..finally is good. with is better.

4. I guess it’s related to programmers’s habit to use try..catch..finally statement from other languages.


回答 2

Python with语句是Resource Acquisition Is InitializationC ++中常用的惯用语的内置语言支持。旨在允许安全获取和释放操作系统资源。

with语句在作用域/块内创建资源。您可以使用块中的资源编写代码。当该块退出时,无论该块中代码的结果如何(即该块是正常退出还是由于异常而退出),资源都会被干净地释放。

Python库中的许多资源都遵循该with语句所需的协议,因此可以立即使用。但是,任何人都可以通过实施有据可查的协议来制作可用于with语句的资源:PEP 0343

每当您在应用程序中获取必须明确放弃的资源(例如文件,网络连接,锁等)时,都应使用它。

The Python with statement is built-in language support of the Resource Acquisition Is Initialization idiom commonly used in C++. It is intended to allow safe acquisition and release of operating system resources.

The with statement creates resources within a scope/block. You write your code using the resources within the block. When the block exits the resources are cleanly released regardless of the outcome of the code in the block (that is whether the block exits normally or because of an exception).

Many resources in the Python library that obey the protocol required by the with statement and so can used with it out-of-the-box. However anyone can make resources that can be used in a with statement by implementing the well documented protocol: PEP 0343

Use it whenever you acquire resources in your application that must be explicitly relinquished such as files, network connections, locks and the like.


回答 3

再次为了完整性,我将添加最有用的with语句用例。

我进行了大量的科学计算,对于某些活动,我需要使用Decimal库来进行任意精度的计算。我的代码的某些部分需要高精度,而对于大多数其他部分,则需要较低的精度。

我将默认精度设置为一个较低的数字,然后使用with来获取某些部分的更精确答案:

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision

我在“超几何测试”中经常使用此功能,该测试需要将大量数字除以形式阶乘。在进行基因组比例计算时,必须注意舍入和溢出错误。

Again for completeness I’ll add my most useful use-case for with statements.

I do a lot of scientific computing and for some activities I need the Decimal library for arbitrary precision calculations. Some part of my code I need high precision and for most other parts I need less precision.

I set my default precision to a low number and then use with to get a more precise answer for some sections:

from decimal import localcontext

with localcontext() as ctx:
    ctx.prec = 42   # Perform a high precision calculation
    s = calculate_something()
s = +s  # Round the final result back to the default precision

I use this a lot with the Hypergeometric Test which requires the division of large numbers resulting form factorials. When you do genomic scale calculations you have to be careful of round-off and overflow errors.


回答 4

反模式的一个例子可能是使用with一个循环内时,它会更有效率有with外循环

例如

for row in lines:
    with open("outfile","a") as f:
        f.write(row)

with open("outfile","a") as f:
    for row in lines:
        f.write(row)

第一种方法是为每个文件打开和关闭文件,row而第二种方法是一次打开和关闭文件,这可能会导致性能问题。

An example of an antipattern might be to use the with inside a loop when it would be more efficient to have the with outside the loop

for example

for row in lines:
    with open("outfile","a") as f:
        f.write(row)

vs

with open("outfile","a") as f:
    for row in lines:
        f.write(row)

The first way is opening and closing the file for each row which may cause performance problems compared to the second way with opens and closes the file just once.


回答 5

参见PEP 343-‘with’语句,最后有一个示例部分。

… Python语言的新语句“ with”使排除try / finally语句的标准用法成为可能。

See PEP 343 – The ‘with’ statement, there is an example section at the end.

… new statement “with” to the Python language to make it possible to factor out standard uses of try/finally statements.


回答 6

第1、2和3点被合理地涵盖了:

4:它相对较新,仅在python2.6 +(或使用的python2.5 from __future__ import with_statement)中可用

points 1, 2, and 3 being reasonably well covered:

4: it is relatively new, only available in python2.6+ (or python2.5 using from __future__ import with_statement)


回答 7

with语句适用于所谓的上下文管理器:

http://docs.python.org/release/2.5.2/lib/typecontextmanager.html

这个想法是通过在离开“ with”块之后进行必要的清理来简化异常处理。一些python内置插件已经可以用作上下文管理器。

The with statement works with so-called context managers:

http://docs.python.org/release/2.5.2/lib/typecontextmanager.html

The idea is to simplify exception handling by doing the necessary cleanup after leaving the ‘with’ block. Some of the python built-ins already work as context managers.


回答 8

开箱即用支持的另一个示例是流行的数据库模块的对象,当您习惯于使用内置open()行为方式时,乍一看可能会感到困惑。connection

这些connection对象是上下文管理器,因此可以直接在中使用with-statement,但是在使用上述说明时,请注意:

with-block完成时,或者与异常或不,该连接不会关闭。万一with-block异常结束,则回滚事务,否则提交事务。

这意味着程序员必须注意自己关闭连接,但允许获取连接,并以多个方式使用它with-statements,如psycopg2 docs中所示:

conn = psycopg2.connect(DSN)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL1)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL2)

conn.close()

在上面的示例中,您会注意到的cursor对象psycopg2也是上下文管理器。从有关行为的相关文档中:

cursor出口退出时,with-block它将关闭,释放最终与之关联的任何资源。交易状态不受影响。

Another example for out-of-the-box support, and one that might be a bit baffling at first when you are used to the way built-in open() behaves, are connection objects of popular database modules such as:

The connection objects are context managers and as such can be used out-of-the-box in a with-statement, however when using the above note that:

When the with-block is finished, either with an exception or without, the connection is not closed. In case the with-block finishes with an exception, the transaction is rolled back, otherwise the transaction is commited.

This means that the programmer has to take care to close the connection themselves, but allows to acquire a connection, and use it in multiple with-statements, as shown in the psycopg2 docs:

conn = psycopg2.connect(DSN)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL1)

with conn:
    with conn.cursor() as curs:
        curs.execute(SQL2)

conn.close()

In the example above, you’ll note that the cursor objects of psycopg2 also are context managers. From the relevant documentation on the behavior:

When a cursor exits the with-block it is closed, releasing any resource eventually associated with it. The state of the transaction is not affected.


回答 9

在python中,通常使用“ with ”语句来打开文件,处理文件中存在的数据,以及不调用close()方法而关闭文件。“ with”语句通过提供清理活动使异常处理更加简单。

的一般形式:

with open(“file name”, mode”) as file-var:
    processing statements

注意:无需通过在file-var.close()上调用close()来关闭文件

In python generally “with” statement is used to open a file, process the data present in the file, and also to close the file without calling a close() method. “with” statement makes the exception handling simpler by providing cleanup activities.

General form of with:

with open(“file name”, “mode”) as file-var:
    processing statements

note: no need to close the file by calling close() upon file-var.close()


如何列出Python模块中的所有功能?

问题:如何列出Python模块中的所有功能?

我的系统上安装了python模块,我希望能够看到其中可用的函数/类/方法。

我想在每个函数上调用doc函数。在ruby中,我可以执行ClassName.methods之类的操作来获取该类上所有可用方法的列表。python中是否有类似的东西?

例如。就像是:

from somemodule import foo
print foo.methods # or whatever is the correct method to call

I have a python module installed on my system and I’d like to be able to see what functions/classes/methods are available in it.

I want to call the doc function on each one. In ruby I can do something like ClassName.methods to get a list of all the methods available on that class. Is there something similar in python?

eg. something like:

from somemodule import foo
print foo.methods # or whatever is the correct method to call

回答 0

inspect模块。另请参阅pydoc模块,help()交互式解释器中的功能以及pydoc生成所需文档的命令行工具。您可以给他们想要查看其文档的类。他们还可以生成例如HTML输出并将其写入磁盘。

The inspect module. Also see the pydoc module, the help() function in the interactive interpreter and the pydoc command-line tool which generates the documentation you are after. You can just give them the class you wish to see the documentation of. They can also generate, for instance, HTML output and write it to disk.


回答 1

您可以dir(module)用来查看所有可用的方法/属性。还要检查PyDocs。

You can use dir(module) to see all available methods/attributes. Also check out PyDocs.


回答 2

一旦你import编的模块,你可以做:

 help(modulename)

…要一次以交互方式获取所有功能的文档。或者您可以使用:

 dir(modulename)

…简单列出模块中定义的所有函数和变量的名称。

Once you’ve imported the module, you can just do:

 help(modulename)

… To get the docs on all the functions at once, interactively. Or you can use:

 dir(modulename)

… To simply list the names of all the functions and variables defined in the module.


回答 3

带inspect的例子:

from inspect import getmembers, isfunction
from my_project import my_module

functions_list = [o for o in getmembers(my_module) if isfunction(o[1])]

getmembers返回(object_name,object_type)元组的列表。

您可以在检查模块中将isfunction替换为任何其他isXXX函数。

An example with inspect:

from inspect import getmembers, isfunction
from my_project import my_module

functions_list = [o for o in getmembers(my_module) if isfunction(o[1])]

getmembers returns a list of (object_name, object_type) tuples.

You can replace isfunction with any of the other isXXX functions in the inspect module.


回答 4

import types
import yourmodule

print([getattr(yourmodule, a) for a in dir(yourmodule)
  if isinstance(getattr(yourmodule, a), types.FunctionType)])
import types
import yourmodule

print([getattr(yourmodule, a) for a in dir(yourmodule)
  if isinstance(getattr(yourmodule, a), types.FunctionType)])

回答 5

为了完整起见,我想指出,有时您可能想解析代码而不是导入代码。一个import执行最高水平的表达,这可能是一个问题。

例如,我让用户为zipapp制作的软件包选择入口点功能。使用误入歧途的代码importinspect冒着导致误入歧途的风险,从而导致崩溃,打印帮助信息,弹出GUI对话框等。

相反,我使用ast模块列出所有顶级功能:

import ast
import sys

def top_level_functions(body):
    return (f for f in body if isinstance(f, ast.FunctionDef))

def parse_ast(filename):
    with open(filename, "rt") as file:
        return ast.parse(file.read(), filename=filename)

if __name__ == "__main__":
    for filename in sys.argv[1:]:
        print(filename)
        tree = parse_ast(filename)
        for func in top_level_functions(tree.body):
            print("  %s" % func.name)

将这段代码放入list.py并用作输入,我得到:

$ python list.py list.py
list.py
  top_level_functions
  parse_ast

当然,即使对于像Python这样的相对简单的语言,导航AST有时也会很棘手,因为AST的层次很低。但是,如果您有一个简单明了的用例,那么它既可行又安全。

不过,缺点是您无法检测到运行时生成的函数,例如foo = lambda x,y: x*y

For completeness’ sake, I’d like to point out that sometimes you may want to parse code instead of importing it. An import will execute top-level expressions, and that could be a problem.

For example, I’m letting users select entry point functions for packages being made with zipapp. Using import and inspect risks running astray code, leading to crashes, help messages being printed out, GUI dialogs popping up and so on.

Instead I use the ast module to list all the top-level functions:

import ast
import sys

def top_level_functions(body):
    return (f for f in body if isinstance(f, ast.FunctionDef))

def parse_ast(filename):
    with open(filename, "rt") as file:
        return ast.parse(file.read(), filename=filename)

if __name__ == "__main__":
    for filename in sys.argv[1:]:
        print(filename)
        tree = parse_ast(filename)
        for func in top_level_functions(tree.body):
            print("  %s" % func.name)

Putting this code in list.py and using itself as input, I get:

$ python list.py list.py
list.py
  top_level_functions
  parse_ast

Of course, navigating an AST can be tricky sometimes, even for a relatively simple language like Python, because the AST is quite low-level. But if you have a simple and clear use case, it’s both doable and safe.

Though, a downside is that you can’t detect functions that are generated at runtime, like foo = lambda x,y: x*y.


回答 6

对于您不希望解析的代码,我建议上面使用基于AST的@csl方法。

对于其他所有内容,inspect模块都是正确的:

import inspect

import <module_to_inspect> as module

functions = inspect.getmembers(module, inspect.isfunction)

这给出了形式为2元组的列表[(<name:str>, <value:function>), ...]

上面的简单答案在各种回复和评论中都有提示,但没有明确指出。

For code that you do not wish to parse, I recommend the AST-based approach of @csl above.

For everything else, the inspect module is correct:

import inspect

import <module_to_inspect> as module

functions = inspect.getmembers(module, inspect.isfunction)

This gives a list of 2-tuples in the form [(<name:str>, <value:function>), ...].

The simple answer above is hinted at in various responses and comments, but not called out explicitly.


回答 7

这将达到目的:

dir(module) 

但是,如果您发现读取返回的列表很烦人,则只需使用以下循环即可获得每行一个名称。

for i in dir(module): print i

This will do the trick:

dir(module) 

However, if you find it annoying to read the returned list, just use the following loop to get one name per line.

for i in dir(module): print i

回答 8

dir(module) 如大多数答案中所述,这是使用脚本或标准解释器时的标准方法。

但是,使用像IPython这样的交互式python shell,您可以使用tab-completion来概述模块中定义的所有对象。这比使用脚本并print查看模块中定义的内容要方便得多。

  • module.<tab> 将向您显示模块中定义的所有对象(函数,类等)
  • module.ClassX.<tab> 将向您展示类的方法和属性
  • module.function_xy?module.ClassX.method_xy?将向您显示该函数/方法的文档字符串
  • module.function_x??module.SomeClass.method_xy??将显示函数/方法的源代码。

dir(module) is the standard way when using a script or the standard interpreter, as mentioned in most answers.

However with an interactive python shell like IPython you can use tab-completion to get an overview of all objects defined in the module. This is much more convenient, than using a script and print to see what is defined in the module.

  • module.<tab> will show you all objects defined in the module (functions, classes and so on)
  • module.ClassX.<tab> will show you the methods and attributes of a class
  • module.function_xy? or module.ClassX.method_xy? will show you the docstring of that function / method
  • module.function_x?? or module.SomeClass.method_xy?? will show you the source code of the function / method.

回答 9

对于全局函数,dir()是要使用的命令(如大多数答案中所提到的),但是此命令同时列出了公共函数和非公共函数。

例如运行:

>>> import re
>>> dir(re)

返回类似的函数/类:

'__all__', '_MAXCACHE', '_alphanum_bytes', '_alphanum_str', '_pattern_type', '_pickle', '_subx'

其中一些通常不用于一般编程用途(但由模块本身提供,除非在DunderAliases之类的情况下, __doc____file__ECT)。因此,将它们与公开对象一起列出可能没有用(这是Python知道使用时会得到什么的方式from module import *)。

__all__可用于解决此问题,它会返回模块中所有公共函数和类的列表(这些函数和类以下划线开头-_)。请参见 有人可以用Python解释__all__吗?用于__all__

这是一个例子:

>>> import re
>>> re.__all__
['match', 'fullmatch', 'search', 'sub', 'subn', 'split', 'findall', 'finditer', 'compile', 'purge', 'template', 'escape', 'error', 'A', 'I', 'L', 'M', 'S', 'X', 'U', 'ASCII', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL', 'VERBOSE', 'UNICODE']
>>>

所有带下划线的函数和类均已删除,仅保留那些定义为public的函数和类,因此可以通过来使用import *

请注意,__all__并非总是定义。如果不包括在内,则AttributeError则引发一个。

ast模块就是一个例子:

>>> import ast
>>> ast.__all__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'ast' has no attribute '__all__'
>>>

For global functions dir() is the command to use (as mentioned in most of these answers), however this lists both public functions and non-public functions together.

For example running:

>>> import re
>>> dir(re)

Returns functions/classes like:

'__all__', '_MAXCACHE', '_alphanum_bytes', '_alphanum_str', '_pattern_type', '_pickle', '_subx'

Some of which are not generally meant for general programming use (but by the module itself, except in the case of DunderAliases like __doc__, __file__ ect). For this reason it may not be useful to list them with the public ones (this is how Python knows what to get when using from module import *).

__all__ could be used to solve this problem, it returns a list of all the public functions and classes in a module (those that do not start with underscores – _). See Can someone explain __all__ in Python? for the use of __all__.

Here is an example:

>>> import re
>>> re.__all__
['match', 'fullmatch', 'search', 'sub', 'subn', 'split', 'findall', 'finditer', 'compile', 'purge', 'template', 'escape', 'error', 'A', 'I', 'L', 'M', 'S', 'X', 'U', 'ASCII', 'IGNORECASE', 'LOCALE', 'MULTILINE', 'DOTALL', 'VERBOSE', 'UNICODE']
>>>

All the functions and classes with underscores have been removed, leaving only those that are defined as public and can therefore be used via import *.

Note that __all__ is not always defined. If it is not included then an AttributeError is raised.

A case of this is with the ast module:

>>> import ast
>>> ast.__all__
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: module 'ast' has no attribute '__all__'
>>>

回答 10

如果您无法在没有导入错误的情况下导入所述Python文件,则这些答案均无效。当我检查文件时,我的情况就是这样,该文件来自具有很多依赖关系的大型代码库。下面将以文本形式处理文件,并搜索所有以“ def”开头的方法名称,并打印它们及其行号。

import re
pattern = re.compile("def (.*)\(")
for i, line in enumerate(open('Example.py')):
  for match in re.finditer(pattern, line):
    print '%s: %s' % (i+1, match.groups()[0])

None of these answers will work if you are unable to import said Python file without import errors. This was the case for me when I was inspecting a file which comes from a large code base with a lot of dependencies. The following will process the file as text and search for all method names that start with “def” and print them and their line numbers.

import re
pattern = re.compile("def (.*)\(")
for i, line in enumerate(open('Example.py')):
  for match in re.finditer(pattern, line):
    print '%s: %s' % (i+1, match.groups()[0])

回答 11

除了前面的答案中提到的dir(模块)或help(模块),您还可以尝试:
-打开ipython-
导入module_name-
键入module_name,然后按tab。它将打开一个小窗口,其中列出了python模块中的所有功能。
看起来很整洁。

这是列出hashlib模块所有功能的代码段

(C:\Program Files\Anaconda2) C:\Users\lenovo>ipython
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import hashlib

In [2]: hashlib.
             hashlib.algorithms            hashlib.new                   hashlib.sha256
             hashlib.algorithms_available  hashlib.pbkdf2_hmac           hashlib.sha384
             hashlib.algorithms_guaranteed hashlib.sha1                  hashlib.sha512
             hashlib.md5                   hashlib.sha224

Except dir(module) or help(module) mentioned in previous answers, you can also try:
– Open ipython
– import module_name
– type module_name, press tab. It’ll open a small window with listing all functions in the python module.
It looks very neat.

Here is snippet listing all functions of hashlib module

(C:\Program Files\Anaconda2) C:\Users\lenovo>ipython
Python 2.7.12 |Anaconda 4.2.0 (64-bit)| (default, Jun 29 2016, 11:07:13) [MSC v.1500 64 bit (AMD64)]
Type "copyright", "credits" or "license" for more information.

IPython 5.1.0 -- An enhanced Interactive Python.
?         -> Introduction and overview of IPython's features.
%quickref -> Quick reference.
help      -> Python's own help system.
object?   -> Details about 'object', use 'object??' for extra details.

In [1]: import hashlib

In [2]: hashlib.
             hashlib.algorithms            hashlib.new                   hashlib.sha256
             hashlib.algorithms_available  hashlib.pbkdf2_hmac           hashlib.sha384
             hashlib.algorithms_guaranteed hashlib.sha1                  hashlib.sha512
             hashlib.md5                   hashlib.sha224

回答 12

这将在列表中附加在your_module中定义的所有功能。

result=[]
for i in dir(your_module):
    if type(getattr(your_module, i)).__name__ == "function":
        result.append(getattr(your_module, i))

This will append all the functions that are defined in your_module in a list.

result=[]
for i in dir(your_module):
    if type(getattr(your_module, i)).__name__ == "function":
        result.append(getattr(your_module, i))

回答 13

您可以使用以下方法从shell列出模块中的所有功能:

import module

module.*?

You can use the following method to get list all the functions in your module from shell:

import module

module.*?

回答 14

import sys
from inspect import getmembers, isfunction
fcn_list = [o[0] for o in getmembers(sys.modules[__name__], isfunction)]
import sys
from inspect import getmembers, isfunction
fcn_list = [o[0] for o in getmembers(sys.modules[__name__], isfunction)]

回答 15

r = globals()
sep = '\n'+100*'*'+'\n' # To make it clean to read.
for k in list(r.keys()):
    try:
        if str(type(r[k])).count('function'):
            print(sep+k + ' : \n' + str(r[k].__doc__))
    except Exception as e:
        print(e)

输出:

******************************************************************************************
GetNumberOfWordsInTextFile : 

    Calcule et retourne le nombre de mots d'un fichier texte
    :param path_: le chemin du fichier à analyser
    :return: le nombre de mots du fichier

******************************************************************************************

    write_in : 

        Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode a,
        :param path_: le path du fichier texte
        :param data_: la liste des données à écrire ou un bloc texte directement
        :return: None


 ******************************************************************************************
    write_in_as_w : 

            Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode w,
            :param path_: le path du fichier texte
            :param data_: la liste des données à écrire ou un bloc texte directement
            :return: None
r = globals()
sep = '\n'+100*'*'+'\n' # To make it clean to read.
for k in list(r.keys()):
    try:
        if str(type(r[k])).count('function'):
            print(sep+k + ' : \n' + str(r[k].__doc__))
    except Exception as e:
        print(e)

Output :

******************************************************************************************
GetNumberOfWordsInTextFile : 

    Calcule et retourne le nombre de mots d'un fichier texte
    :param path_: le chemin du fichier à analyser
    :return: le nombre de mots du fichier

******************************************************************************************

    write_in : 

        Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode a,
        :param path_: le path du fichier texte
        :param data_: la liste des données à écrire ou un bloc texte directement
        :return: None


 ******************************************************************************************
    write_in_as_w : 

            Ecrit les donnees (2nd arg) dans un fichier txt (path en 1st arg) en mode w,
            :param path_: le path du fichier texte
            :param data_: la liste des données à écrire ou un bloc texte directement
            :return: None

__getattr__和__getattribute__之间的区别

问题:__getattr__和__getattribute__之间的区别

我想了解何时使用__getattr____getattribute__。该文件提到了__getattribute__适用于新样式类。什么是新型类?

I am trying to understand when to use __getattr__ or __getattribute__. The documentation mentions __getattribute__ applies to new-style classes. What are new-style classes?


回答 0

之间的主要差异__getattr__,并__getattribute__是,__getattr__如果属性没有被发现通常的途径,只调用。这对于实现缺少属性的后备方法很有用,并且可能是您想要的两个之一。

__getattribute__在查看对象的实际属性之前调用,因此正确实现可能会比较棘手。您可以非常轻松地进行无限递归。

新样式类是从派生而来的object,旧样式类是Python 2.x中没有显式基类的类。但旧式和新式的类之间的区别并不之间进行选择时的重要的__getattr____getattribute__

您几乎可以肯定想要__getattr__

A key difference between __getattr__ and __getattribute__ is that __getattr__ is only invoked if the attribute wasn’t found the usual ways. It’s good for implementing a fallback for missing attributes, and is probably the one of two you want.

__getattribute__ is invoked before looking at the actual attributes on the object, and so can be tricky to implement correctly. You can end up in infinite recursions very easily.

New-style classes derive from object, old-style classes are those in Python 2.x with no explicit base class. But the distinction between old-style and new-style classes is not the important one when choosing between __getattr__ and __getattribute__.

You almost certainly want __getattr__.


回答 1

让我们来看看两者的一些简单的例子__getattr____getattribute__魔术方法。

__getattr__

__getattr__每当您请求尚未定义的属性时,Python都会调用 method。在下面的示例中,我的Count类没有__getattr__方法。现在,当我尝试同时访问obj1.mymin和访问obj1.mymax属性时,一切正常。但是当我尝试访问obj1.mycurrent属性时-Python给了我AttributeError: 'Count' object has no attribute 'mycurrent'

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

现在,我的ClassCount具有__getattr__方法。现在,当我尝试访问 obj1.mycurrent属性时-python返回我在__getattr__方法中实现的内容。在我的示例中,每当我尝试调用不存在的属性时,python都会创建该属性并将其设置为整数值0。

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

__getattribute__

现在让我们看一下__getattribute__方法。如果您__getattribute__的类中有 方法,则python会为每个属性调用此方法,无论该属性是否存在。那么为什么我们需要__getattribute__方法呢?一个很好的理由是,您可以阻止访问属性并使它们更安全,如以下示例所示。

每当有人尝试访问以子字符串“ cur”开头的我的属性时,python都会引发AttributeError异常。否则,它将返回该属性。

class Count:

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item) 
        # or you can use ---return super().__getattribute__(item)

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

重要说明:为了避免__getattribute__方法中的无限递归,其实现应始终调用具有相同名称的基类方法以访问其所需的任何属性。例如:object.__getattribute__(self, name)super().__getattribute__(item)self.__dict__[item]

重要

如果您的类同时包含getattrgetattribute魔术方法,则将__getattribute__首先调用该方法 。但是,如果 __getattribute__引发 AttributeError异常,则该异常将被忽略,__getattr__方法将被调用。请参见以下示例:

class Count(object):

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattr__(self, item):
            self.__dict__[item]=0
            return 0

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item)
        # or you can use ---return super().__getattribute__(item)
        # note this class subclass object

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

Lets see some simple examples of both __getattr__ and __getattribute__ magic methods.

__getattr__

Python will call __getattr__ method whenever you request an attribute that hasn’t already been defined. In the following example my class Count has no __getattr__ method. Now in main when I try to access both obj1.mymin and obj1.mymax attributes everything works fine. But when I try to access obj1.mycurrent attribute — Python gives me AttributeError: 'Count' object has no attribute 'mycurrent'

class Count():
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent)  --> AttributeError: 'Count' object has no attribute 'mycurrent'

Now my class Count has __getattr__ method. Now when I try to access obj1.mycurrent attribute — python returns me whatever I have implemented in my __getattr__ method. In my example whenever I try to call an attribute which doesn’t exist, python creates that attribute and set it to integer value 0.

class Count:
    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax    

    def __getattr__(self, item):
        self.__dict__[item]=0
        return 0

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.mycurrent1)

__getattribute__

Now lets see the __getattribute__ method. If you have __getattribute__ method in your class, python invokes this method for every attribute regardless whether it exists or not. So why we need __getattribute__ method? One good reason is that you can prevent access to attributes and make them more secure as shown in the following example.

Whenever someone try to access my attributes that starts with substring ‘cur’ python raises AttributeError exception. Otherwise it returns that attribute.

class Count:

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item) 
        # or you can use ---return super().__getattribute__(item)

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

Important: In order to avoid infinite recursion in __getattribute__ method, its implementation should always call the base class method with the same name to access any attributes it needs. For example: object.__getattribute__(self, name) or super().__getattribute__(item) and not self.__dict__[item]

IMPORTANT

If your class contain both getattr and getattribute magic methods then __getattribute__ is called first. But if __getattribute__ raises AttributeError exception then the exception will be ignored and __getattr__ method will be invoked. See the following example:

class Count(object):

    def __init__(self,mymin,mymax):
        self.mymin=mymin
        self.mymax=mymax
        self.current=None

    def __getattr__(self, item):
            self.__dict__[item]=0
            return 0

    def __getattribute__(self, item):
        if item.startswith('cur'):
            raise AttributeError
        return object.__getattribute__(self,item)
        # or you can use ---return super().__getattribute__(item)
        # note this class subclass object

obj1 = Count(1,10)
print(obj1.mymin)
print(obj1.mymax)
print(obj1.current)

回答 2

这只是基于Ned Batchelder的解释的示例

__getattr__ 例:

class Foo(object):
    def __getattr__(self, attr):
        print "looking up", attr
        value = 42
        self.__dict__[attr] = value
        return value

f = Foo()
print f.x 
#output >>> looking up x 42

f.x = 3
print f.x 
#output >>> 3

print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')

如果使用相同的示例,__getattribute__您将得到>>>RuntimeError: maximum recursion depth exceeded while calling a Python object

This is just an example based on Ned Batchelder’s explanation.

__getattr__ example:

class Foo(object):
    def __getattr__(self, attr):
        print "looking up", attr
        value = 42
        self.__dict__[attr] = value
        return value

f = Foo()
print f.x 
#output >>> looking up x 42

f.x = 3
print f.x 
#output >>> 3

print ('__getattr__ sets a default value if undefeined OR __getattr__ to define how to handle attributes that are not found')

And if same example is used with __getattribute__ You would get >>> RuntimeError: maximum recursion depth exceeded while calling a Python object


回答 3

新样式类继承自object,或从另一个新样式类继承:

class SomeObject(object):
    pass

class SubObject(SomeObject):
    pass

旧式类不能:

class SomeObject:
    pass

这仅适用于Python 2-在Python 3中,以上所有内容都会创建新样式的类。

请参见9.类(Python教程),NewClassVsClassicClass和Python中旧样式类和新样式类之间的区别是什么?有关详细信息。

New-style classes inherit from object, or from another new style class:

class SomeObject(object):
    pass

class SubObject(SomeObject):
    pass

Old-style classes don’t:

class SomeObject:
    pass

This only applies to Python 2 – in Python 3 all the above will create new-style classes.

See 9. Classes (Python tutorial), NewClassVsClassicClass and What is the difference between old style and new style classes in Python? for details.


回答 4

新型类是子类“对象”的子类(直接或间接)。他们除了具有__new__类方法外__init__,还具有更合理的低级行为。

通常,您将需要覆盖__getattr__(如果要覆盖两者之一),否则您将很难在方法中支持“ self.foo”语法。

额外信息:http : //www.devx.com/opensource/Article/31482/0/page/4

New-style classes are ones that subclass “object” (directly or indirectly). They have a __new__ class method in addition to __init__ and have somewhat more rational low-level behavior.

Usually, you’ll want to override __getattr__ (if you’re overriding either), otherwise you’ll have a hard time supporting “self.foo” syntax within your methods.

Extra info: http://www.devx.com/opensource/Article/31482/0/page/4


回答 5

在阅读Beazley&Jones PCB时,我偶然发现了一个明确而实际的用例,__getattr__该用例有助于回答OP的“何时”部分。从书中:

“该__getattr__()方法有点像属性查找的全部。如果代码尝试访问不存在的属性,则该方法会被调用。” 我们从以上答案中知道了这一点,但是在PCB配方8.15中,此功能用于实现委托设计模式。如果对象A具有对象B的属性,该属性实现了对象A要委派的许多方法,而不是仅在调用对象B的方法时重新定义对象A中的对象B的所有方法,请定义一个__getattr__()方法,如下所示:

def __getattr__(self, name):
    return getattr(self._b, name)

其中_b是对象A的属性名称,即对象B。在对象A上调用在对象B上定义的__getattr__方法时,该方法将在查找链的末尾被调用。这也将使代码更简洁,因为您没有定义仅用于委派给另一个对象的方法列表。

In reading through Beazley & Jones PCB, I have stumbled on an explicit and practical use-case for __getattr__ that helps answer the “when” part of the OP’s question. From the book:

“The __getattr__() method is kind of like a catch-all for attribute lookup. It’s a method that gets called if code tries to access an attribute that doesn’t exist.” We know this from the above answers, but in PCB recipe 8.15, this functionality is used to implement the delegation design pattern. If Object A has an attribute Object B that implements many methods that Object A wants to delegate to, rather than redefining all of Object B’s methods in Object A just to call Object B’s methods, define a __getattr__() method as follows:

def __getattr__(self, name):
    return getattr(self._b, name)

where _b is the name of Object A’s attribute that is an Object B. When a method defined on Object B is called on Object A, the __getattr__ method will be invoked at the end of the lookup chain. This would make code cleaner as well, since you do not have a list of methods defined just for delegating to another object.


如何对字符串列表进行排序?

问题:如何对字符串列表进行排序?

在Python中创建按字母顺序排序的列表的最佳方法是什么?

What is the best way of creating an alphabetically sorted list in Python?


回答 0

基本答案:

mylist = ["b", "C", "A"]
mylist.sort()

这会修改您的原始列表(即就地排序)。要获得列表的排序副本,而无需更改原始副本,请使用以下sorted()函数:

for x in sorted(mylist):
    print x

但是,上面的示例有些天真,因为它们没有考虑区域设置,而是执行区分大小写的排序。您可以利用可选参数key指定自定义排序顺序(使用的替代方法cmp是不推荐使用的解决方案,因为它必须多次评估- key每个元素仅计算一次)。

因此,要根据当前语言环境进行排序,并考虑到特定于语言的规则(这cmp_to_key是functools的帮助函数):

sorted(mylist, key=cmp_to_key(locale.strcoll))

最后,如果需要,您可以指定自定义语言环境进行排序:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale
assert sorted((u'Ab', u'ad', u'aa'),
  key=cmp_to_key(locale.strcoll)) == [u'aa', u'Ab', u'ad']

最后要注意的是:您将看到使用该lower()方法的不区分大小写的排序示例-这些是不正确的,因为它们仅适用于ASCII字符子集。对于任何非英语数据,这两个错误:

# this is incorrect!
mylist.sort(key=lambda x: x.lower())
# alternative notation, a bit faster, but still wrong
mylist.sort(key=str.lower)

Basic answer:

mylist = ["b", "C", "A"]
mylist.sort()

This modifies your original list (i.e. sorts in-place). To get a sorted copy of the list, without changing the original, use the sorted() function:

for x in sorted(mylist):
    print x

However, the examples above are a bit naive, because they don’t take locale into account, and perform a case-sensitive sorting. You can take advantage of the optional parameter key to specify custom sorting order (the alternative, using cmp, is a deprecated solution, as it has to be evaluated multiple times – key is only computed once per element).

So, to sort according to the current locale, taking language-specific rules into account (cmp_to_key is a helper function from functools):

sorted(mylist, key=cmp_to_key(locale.strcoll))

And finally, if you need, you can specify a custom locale for sorting:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale
assert sorted((u'Ab', u'ad', u'aa'),
  key=cmp_to_key(locale.strcoll)) == [u'aa', u'Ab', u'ad']

Last note: you will see examples of case-insensitive sorting which use the lower() method – those are incorrect, because they work only for the ASCII subset of characters. Those two are wrong for any non-English data:

# this is incorrect!
mylist.sort(key=lambda x: x.lower())
# alternative notation, a bit faster, but still wrong
mylist.sort(key=str.lower)

回答 1

还值得注意的sorted()功能:

for x in sorted(list):
    print x

这将返回列表的新排序版本,而不更改原始列表。

It is also worth noting the sorted() function:

for x in sorted(list):
    print x

This returns a new, sorted version of a list without changing the original list.


回答 2

list.sort()

真的就是这么简单:)

list.sort()

It really is that simple :)


回答 3

字符串排序的正确方法是:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale
assert sorted((u'Ab', u'ad', u'aa'), cmp=locale.strcoll) == [u'aa', u'Ab', u'ad']

# Without using locale.strcoll you get:
assert sorted((u'Ab', u'ad', u'aa')) == [u'Ab', u'aa', u'ad']

前面的示例mylist.sort(key=lambda x: x.lower())对于仅ASCII上下文适用。

The proper way to sort strings is:

import locale
locale.setlocale(locale.LC_ALL, 'en_US.UTF-8') # vary depending on your lang/locale
assert sorted((u'Ab', u'ad', u'aa'), cmp=locale.strcoll) == [u'aa', u'Ab', u'ad']

# Without using locale.strcoll you get:
assert sorted((u'Ab', u'ad', u'aa')) == [u'Ab', u'aa', u'ad']

The previous example of mylist.sort(key=lambda x: x.lower()) will work fine for ASCII-only contexts.


回答 4

请在Python3中使用sorted()函数

items = ["love", "like", "play", "cool", "my"]
sorted(items2)

Please use sorted() function in Python3

items = ["love", "like", "play", "cool", "my"]
sorted(items2)

回答 5

但是,这如何处理特定于语言的排序规则?是否考虑到语言环境?

不,list.sort()是通用排序功能。如果要根据Unicode规则进行排序,则必须定义一个自定义的排序键函数。您可以尝试使用pyuca模块,但我不知道它的完整性。

But how does this handle language specific sorting rules? Does it take locale into account?

No, list.sort() is a generic sorting function. If you want to sort according to the Unicode rules, you’ll have to define a custom sort key function. You can try using the pyuca module, but I don’t know how complete it is.


回答 6

这是一个老问题,但是如果您想在不进行设置的情况下进行 locale.LC_ALL感知区域设置的排序,则可以按照此答案的建议使用PyICU库

import icu # PyICU

def sorted_strings(strings, locale=None):
    if locale is None:
       return sorted(strings)
    collator = icu.Collator.createInstance(icu.Locale(locale))
    return sorted(strings, key=collator.getSortKey)

然后用例如:

new_list = sorted_strings(list_of_strings, "de_DE.utf8")

这对我有用,而无需安装任何语言环境或更改其他系统设置。

(这已经在上面的评论中建议,但是我想让它更加突出,因为我一开始就很想念它。)

Old question, but if you want to do locale-aware sorting without setting locale.LC_ALL you can do so by using the PyICU library as suggested by this answer:

import icu # PyICU

def sorted_strings(strings, locale=None):
    if locale is None:
       return sorted(strings)
    collator = icu.Collator.createInstance(icu.Locale(locale))
    return sorted(strings, key=collator.getSortKey)

Then call with e.g.:

new_list = sorted_strings(list_of_strings, "de_DE.utf8")

This worked for me without installing any locales or changing other system settings.

(This was already suggested in a comment above, but I wanted to give it more prominence, because I missed it myself at first.)


回答 7

假设 s = "ZWzaAd"

要在字符串上方排序,简单的解决方案将是在字符串下方。

print ''.join(sorted(s))

Suppose s = "ZWzaAd"

To sort above string the simple solution will be below one.

print ''.join(sorted(s))

回答 8

或许:

names = ['Jasmine', 'Alberto', 'Ross', 'dig-dog']
print ("The solution for this is about this names being sorted:",sorted(names, key=lambda name:name.lower()))

Or maybe:

names = ['Jasmine', 'Alberto', 'Ross', 'dig-dog']
print ("The solution for this is about this names being sorted:",sorted(names, key=lambda name:name.lower()))

回答 9

l =['abc' , 'cd' , 'xy' , 'ba' , 'dc']
l.sort()
print(l1)

结果

[‘abc’,’ba’,’cd’,’dc’,’xy’]

l =['abc' , 'cd' , 'xy' , 'ba' , 'dc']
l.sort()
print(l1)

Result

[‘abc’, ‘ba’, ‘cd’, ‘dc’, ‘xy’]


回答 10

很简单:https : //trinket.io/library/trinkets/5db81676e4

scores = '54 - Alice,35 - Bob,27 - Carol,27 - Chuck,05 - Craig,30 - Dan,27 - Erin,77 - Eve,14 - Fay,20 - Frank,48 - Grace,61 - Heidi,03 - Judy,28 - Mallory,05 - Olivia,44 - Oscar,34 - Peggy,30 - Sybil,82 - Trent,75 - Trudy,92 - Victor,37 - Walter'

得分= scores.split(’,’)for x in sorted(scores):print(x)

It is simple: https://trinket.io/library/trinkets/5db81676e4

scores = '54 - Alice,35 - Bob,27 - Carol,27 - Chuck,05 - Craig,30 - Dan,27 - Erin,77 - Eve,14 - Fay,20 - Frank,48 - Grace,61 - Heidi,03 - Judy,28 - Mallory,05 - Olivia,44 - Oscar,34 - Peggy,30 - Sybil,82 - Trent,75 - Trudy,92 - Victor,37 - Walter'

scores = scores.split(‘,’) for x in sorted(scores): print(x)


如何保存Python交互式会话?

问题:如何保存Python交互式会话?

我发现自己经常使用Python的解释器来处理数据库,文件等-基本上是半结构化数据的大量手动格式化。我没有按我的意愿正确地保存和清理有用的位。有没有一种方法可以将我的输入保存到外壳中(数据库连接,变量分配,很少用于循环和逻辑位)-交互式会话的一些历史记录?如果我使用类似的东西,script则会收到过多的标准输出噪音。我真的不需要腌制所有对象-尽管如果有解决方案可以做到这一点,那就可以了。理想情况下,我只剩下一个脚本,该脚本可以像我交互式创建的那样运行,并且我可以删除不需要的部分。是否有这样做的包装或DIY方法?

更新:我对这些软件包的质量和实用性感到非常惊讶。对于那些类似的痒:

  • IPython-早就应该使用它了
  • 重新互动 -非常令人印象深刻,我想了解有关可视化的更多信息,这似乎会在这里闪耀。排序图的gtk / gnome桌面应用程序。想象一下混合壳+图形计算器+迷你月食。此处的源代码分发:http : //www.reinteract.org/trac/wiki/GettingIt。可以在Ubuntu上很好地构建,也可以集成到gnome桌面,Windows和Mac安装程序中。
  • bpython-非常酷,有很多不错的功能,自动完成(!),倒带,一键保存到文件,缩进,做得很好。Python源代码发行版从sourceforge中提取了两个依赖项。

我被转换了,这些真的满足了解释器和编辑器之间的需求。

I find myself frequently using Python’s interpreter to work with databases, files, etc — basically a lot of manual formatting of semi-structured data. I don’t properly save and clean up the useful bits as often as I would like. Is there a way to save my input into the shell (db connections, variable assignments, little for loops and bits of logic) — some history of the interactive session? If I use something like script I get too much stdout noise. I don’t really need to pickle all the objects — though if there is a solution that does that, it would be OK. Ideally I would just be left with a script that ran as the one I created interactively, and I could just delete the bits I didn’t need. Is there a package that does this, or a DIY approach?

UPDATE: I am really amazed at the quality and usefulness of these packages. For those with a similar itch:

  • IPython — should have been using this for ages, kind of what I had in mind
  • reinteract — very impressive, I want to learn more about visualization and this seems like it will shine there. Sort of a gtk/gnome desktop app that renders graphs inline. Imagine a hybrid shell + graphing calculator + mini eclipse. Source distribution here: http://www.reinteract.org/trac/wiki/GettingIt . Built fine on Ubuntu, integrates into gnome desktop, Windows and Mac installers too.
  • bpython — extremely cool, lots of nice features, autocomplete(!), rewind, one keystroke save to file, indentation, well done. Python source distribution, pulled a couple of dependencies from sourceforge.

I am converted, these really fill a need between interpreter and editor.


回答 0

如果您喜欢使用交互式会话,则IPython非常有用。例如,对于您的用例,有一个%savemagic命令,您只需输入%save my_useful_session 10-20 23以保存输入行10至20和23至my_useful_session.py(为此,每行都以其编号作为前缀)。

此外,文档指出:

此函数对输入范围使用与%history相同的语法,然后将这些行保存到您指定的文件名中。

例如,这允许引用较旧的会话,例如

%save current_session ~0/
%save previous_session ~1/

观看演示页面的视频,以快速了解这些功能。

IPython is extremely useful if you like using interactive sessions. For example for your use-case there is the %save magic command, you just input %save my_useful_session 10-20 23 to save input lines 10 to 20 and 23 to my_useful_session.py (to help with this, every line is prefixed by its number).

Furthermore, the documentation states:

This function uses the same syntax as %history for input ranges, then saves the lines to the filename you specify.

This allows for example, to reference older sessions, such as

%save current_session ~0/
%save previous_session ~1/

Look at the videos on the presentation page to get a quick overview of the features.


回答 1

http://www.andrewhjon.es/save-interactive-python-session-history

import readline
readline.write_history_file('/home/ahj/history')

http://www.andrewhjon.es/save-interactive-python-session-history

import readline
readline.write_history_file('/home/ahj/history')

回答 2

有一个 方法可以做到。将文件存储在~/.pystartup

# Add auto-completion and a stored history file of commands to your Python
# interactive interpreter. Requires Python 2.0+, readline. Autocomplete is
# bound to the Esc key by default (you can change it - see readline docs).
#
# Store the file in ~/.pystartup, and set an environment variable to point
# to it:  "export PYTHONSTARTUP=/home/user/.pystartup" in bash.
#
# Note that PYTHONSTARTUP does *not* expand "~", so you have to put in the
# full path to your home directory.

import atexit
import os
import readline
import rlcompleter

historyPath = os.path.expanduser("~/.pyhistory")

def save_history(historyPath=historyPath):
    import readline
    readline.write_history_file(historyPath)

if os.path.exists(historyPath):
    readline.read_history_file(historyPath)

atexit.register(save_history)
del os, atexit, readline, rlcompleter, save_history, historyPath

然后PYTHONSTARTUP在您的shell中设置环境变量(例如在中~/.bashrc):

export PYTHONSTARTUP=$HOME/.pystartup

您还可以添加以下内容以免费获取自动完成功能:

readline.parse_and_bind('tab: complete')

请注意,这仅适用于* nix系统。由于readline仅在Unix平台上可用。

There is a way to do it. Store the file in ~/.pystartup

# Add auto-completion and a stored history file of commands to your Python
# interactive interpreter. Requires Python 2.0+, readline. Autocomplete is
# bound to the Esc key by default (you can change it - see readline docs).
#
# Store the file in ~/.pystartup, and set an environment variable to point
# to it:  "export PYTHONSTARTUP=/home/user/.pystartup" in bash.
#
# Note that PYTHONSTARTUP does *not* expand "~", so you have to put in the
# full path to your home directory.

import atexit
import os
import readline
import rlcompleter

historyPath = os.path.expanduser("~/.pyhistory")

def save_history(historyPath=historyPath):
    import readline
    readline.write_history_file(historyPath)

if os.path.exists(historyPath):
    readline.read_history_file(historyPath)

atexit.register(save_history)
del os, atexit, readline, rlcompleter, save_history, historyPath

and then set the environment variable PYTHONSTARTUP in your shell (e.g. in ~/.bashrc):

export PYTHONSTARTUP=$HOME/.pystartup

You can also add this to get autocomplete for free:

readline.parse_and_bind('tab: complete')

Please note that this will only work on *nix systems. As readline is only available in Unix platform.


回答 3

如果使用的是IPython,则可以使用魔术函数%history-f参数pe 将以前的所有命令保存到文件中:

%history -f /tmp/history.py

If you are using IPython you can save to a file all your previous commands using the magic function %history with the -f parameter, p.e:

%history -f /tmp/history.py

回答 4

安装Ipython并通过运行以下命令打开Ipython会话后:

ipython

从命令行中,只需运行以下Ipython’magic’命令以自动记录整个Ipython会话:

%logstart

这将创建一个唯一命名的.py文件,并存储您的会话,以供以后用作交互式Ipython会话或在您选择的脚本中使用。

After installing Ipython, and opening an Ipython session by running the command:

ipython

from your command line, just run the following Ipython ‘magic’ command to automatically log your entire Ipython session:

%logstart

This will create a uniquely named .py file and store your session for later use as an interactive Ipython session or for use in the script(s) of your choosing.


回答 5

同样,重新交互为您提供了类似于笔记本的Python会话界面。

Also, reinteract gives you a notebook-like interface to a Python session.


回答 6

除了IPython,类似的实用程序bpython还具有“将您输入的代码保存到文件中”的功能

In addition to IPython, a similar utility bpython has a “save the code you’ve entered to a file” feature


回答 7

我必须努力寻找答案,我对iPython环境非常陌生。

这会工作

如果您的iPython会话如下所示

In [1] : import numpy as np
....
In [135]: counter=collections.Counter(mapusercluster[3])
In [136]: counter
Out[136]: Counter({2: 700, 0: 351, 1: 233})

您想要保存从1到135的行,然后在同一ipython会话上使用此命令

In [137]: %save test.py 1-135

这会将所有python语句保存在当前目录(启动ipython的位置)的test.py文件中。

I had to struggle to find an answer, I was very new to iPython environment.

This will work

If your iPython session looks like this

In [1] : import numpy as np
....
In [135]: counter=collections.Counter(mapusercluster[3])
In [136]: counter
Out[136]: Counter({2: 700, 0: 351, 1: 233})

You want to save lines from 1 till 135 then on the same ipython session use this command

In [137]: %save test.py 1-135

This will save all your python statements in test.py file in your current directory ( where you initiated the ipython).


回答 8

有%history魔术可用于打印和保存输入历史记录(以及可选的输出)。

要将当前会话存储到名为的文件中my_history.py

>>> %hist -f my_history.py

历史记录IPython既存储您输入的命令,又存储它产生的结果。您可以使用上下箭头键轻松查看以前的命令,或者以更复杂的方式访问历史记录。

您可以使用%history magic函数来检查过去的输入和输出。先前会话的输入历史记录保存在数据库中,并且可以配置IPython来保存输出历史记录。

其他几个魔术功能也可以使用您的输入历史记录,包括%edit,%rerun,%recall,%macro,%save和%pastebin。您可以使用标准格式来引用行:

%pastebin 3 18-20 ~1/1-5

这将占用当前会话的第3行和第18至20行,以及上一会话的第1-5行。

看到%history?Docstring和更多示例。

另外,请确保探索%store magic在IPython中实现变量的轻量级持久性的功能。

在IPython的数据库中存储变量,别名和宏。

d = {'a': 1, 'b': 2}
%store d  # stores the variable
del d

%store -r d  # Refresh the variable from IPython's database.
>>> d
{'a': 1, 'b': 2}

要在启动c.StoreMagic.autorestore = True时自动恢复存储的变量,请在ipython_config.py中指定。

There is %history magic for printing and saving the input history (and optionally the output).

To store your current session to a file named my_history.py:

>>> %hist -f my_history.py

History IPython stores both the commands you enter, and the results it produces. You can easily go through previous commands with the up- and down-arrow keys, or access your history in more sophisticated ways.

You can use the %history magic function to examine past input and output. Input history from previous sessions is saved in a database, and IPython can be configured to save output history.

Several other magic functions can use your input history, including %edit, %rerun, %recall, %macro, %save and %pastebin. You can use a standard format to refer to lines:

%pastebin 3 18-20 ~1/1-5

This will take line 3 and lines 18 to 20 from the current session, and lines 1-5 from the previous session.

See %history? for the Docstring and more examples.

Also, be sure to explore the capabilities of %store magic for lightweight persistence of variables in IPython.

Stores variables, aliases and macros in IPython’s database.

d = {'a': 1, 'b': 2}
%store d  # stores the variable
del d

%store -r d  # Refresh the variable from IPython's database.
>>> d
{'a': 1, 'b': 2}

To autorestore stored variables on startup, specifyc.StoreMagic.autorestore = True in ipython_config.py.


回答 9

只是在碗里放另一个建议: Spyder

在此处输入图片说明

它具有历史记录日志变量资源管理器。如果您使用过MatLab,那么您将看到相似之处。

Just putting another suggesting in the bowl: Spyder

enter image description here

It has History log and Variable explorer. If you have worked with MatLab, then you’ll see the similarities.


回答 10

就Linux而言,人们可以使用script命令来记录整个会话。它是util-linux软件包的一部分,因此应在大多数Linux系统上使用。您可以创建将要调用的别名或函数script -c python,并将其保存到typescript文件中。例如,这是一个这样的文件的重印。

$ cat typescript                                                                                                      
Script started on Sat 14 May 2016 08:30:08 AM MDT
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'Hello Pythonic World'
Hello Pythonic World
>>> 

Script done on Sat 14 May 2016 08:30:42 AM MDT

这里的一个小缺点是script,无论何时碰到退格键等等,它都会记录所有内容,甚至是换行。因此,您可能希望使用它col来清理输出(请参阅Unix&Linux Stackexchange上的这篇文章)。

As far as Linux goes, one can use script command to record the whole session. It is part of util-linux package so should be on most Linux systems . You can create and alias or function that will call script -c python and that will be saved to a typescript file. For instance, here’s a reprint of one such file.

$ cat typescript                                                                                                      
Script started on Sat 14 May 2016 08:30:08 AM MDT
Python 2.7.6 (default, Jun 22 2015, 17:58:13) 
[GCC 4.8.2] on linux2
Type "help", "copyright", "credits" or "license" for more information.
>>> print 'Hello Pythonic World'
Hello Pythonic World
>>> 

Script done on Sat 14 May 2016 08:30:42 AM MDT

Small disadvantage here is that the script records everything , even line-feeds, whenever you hit backspaces , etc. So you may want to use col to clean up the output (see this post on Unix&Linux Stackexchange) .


回答 11

%history命令很棒,但不幸的是,它不会让您将%paste的内容保存到sesh中。为此,我认为您必须在一开始就做%logstart (尽管我尚未确认这项工作有效)。

我喜欢做的是

%history -o -n -p -f filename.txt

它将在每个输入之前保存输出,行号和’>>>’(o,n和p选项)。在此处查看%history的文档。

The %history command is awesome, but unfortunately it won’t let you save things that were %paste ‘d into the sesh. To do that I think you have to do %logstart at the beginning (although I haven’t confirmed this works).

What I like to do is

%history -o -n -p -f filename.txt

which will save the output, line numbers, and ‘>>>’ before each input (o, n, and p options). See the docs for %history here.


回答 12

还有另一种选择— pyslice。在“ wxpython 2.8文档演示和工具”中,有一个名为“ pyslices”的开源程序。

您可以像编辑器一样使用它,它还可以像控制台一样使用—-像执行即时回显的交互式解释器一样执行每一行。

当然,所有代码块和每个块的结果将自动记录到txt文件中。

结果记录在相应的代码块后面。很方便。

切片的概述

there is another option — pyslice. in the “wxpython 2.8 docs demos and tools”, there is a open source program named “pyslices”.

you can use it like a editor, and it also support using like a console —- executing each line like a interactive interpreter with immediate echo.

of course, all the blocks of codes and results of each block will be recorded into a txt file automatically.

the results are logged just behind the corresponding block of code. very convenient.

the overview of pyslices


回答 13

如果使用bpython,则默认情况下所有命令历史记录都保存到~/.pythonhist

要保存命令以供以后重用,可以将它们复制到python脚本文件中:

$ cp ~/.pythonhist mycommands.py

然后编辑该文件以将其清理并放在Python路径(全局或虚拟环境的站点包,当前目录,*。pth中提及或其他方式)下。

要将命令包括到您的shell中,只需从保存的文件中导入它们:

>>> from mycommands import *

If you use bpython, all your command history is by default saved to ~/.pythonhist.

To save the commands for later reusage you can copy them to a python script file:

$ cp ~/.pythonhist mycommands.py

Then edit that file to clean it up and put it under Python path (global or virtual environment’s site-packages, current directory, mentioning in *.pth, or some other way).

To include the commands into your shell, just import them from the saved file:

>>> from mycommands import *

回答 14

一些评论询问如何立即保存所有IPython输入。对于IPython中的%s magic,可以如下所示以编程方式保存所有命令,以避免出现提示消息,也避免指定输入数字。currentLine = len(In)-1%保存-f my_session 1- $ currentLine

-f选项用于强制替换文件,并len(IN)-1在IPython中显示当前输入提示,从而允许您以编程方式保存整个会话。

Some comments were asking how to save all of the IPython inputs at once. For %save magic in IPython, you can save all of the commands programmatically as shown below, to avoid the prompt message and also to avoid specifying the input numbers. currentLine = len(In)-1 %save -f my_session 1-$currentLine

The -f option is used for forcing file replacement and the len(IN)-1 shows the current input prompt in IPython, allowing you to save the whole session programmatically.


回答 15

对于那些使用spacemacsipython附带的用户python-layer,由于在后台运行恒定的自动完成命令,例如save,魔术会产生很多不需要的输出:

len(all_suffixes)
';'.join(__PYTHON_EL_get_completions('''len'''))
';'.join(__PYTHON_EL_get_completions('''all_substa'''))
len(all_substantives_w_suffixes)
';'.join(__PYTHON_EL_get_completions('''len'''))
';'.join(__PYTHON_EL_get_completions('''all'''))
';'.join(__PYTHON_EL_get_completions('''all_'''))
';'.join(__PYTHON_EL_get_completions('''all_w'''))
';'.join(__PYTHON_EL_get_completions('''all_wo'''))
';'.join(__PYTHON_EL_get_completions('''all_wor'''))
';'.join(__PYTHON_EL_get_completions('''all_word'''))
';'.join(__PYTHON_EL_get_completions('''all_words'''))
len(all_words_w_logograms)
len(all_verbs)

为了避免这种情况,只需像平时保存其他任何文件一样保存ipython缓冲区即可: spc f s

For those using spacemacs, and ipython that comes with python-layer, save magic creates a lot of unwanted output, because of the constant auto-completion command working in the backround such as:

len(all_suffixes)
';'.join(__PYTHON_EL_get_completions('''len'''))
';'.join(__PYTHON_EL_get_completions('''all_substa'''))
len(all_substantives_w_suffixes)
';'.join(__PYTHON_EL_get_completions('''len'''))
';'.join(__PYTHON_EL_get_completions('''all'''))
';'.join(__PYTHON_EL_get_completions('''all_'''))
';'.join(__PYTHON_EL_get_completions('''all_w'''))
';'.join(__PYTHON_EL_get_completions('''all_wo'''))
';'.join(__PYTHON_EL_get_completions('''all_wor'''))
';'.join(__PYTHON_EL_get_completions('''all_word'''))
';'.join(__PYTHON_EL_get_completions('''all_words'''))
len(all_words_w_logograms)
len(all_verbs)

To avoid this just save the ipython buffer like you normally save any other: spc f s


回答 16

我想提出另一种在Linux上通过tmux维护python会话的方法。您运行tmux,将自己附加到您打开的会话中(如果直接打开后未附加)。执行python并在上面执行任何操作。然后脱离会话。从tmux会话中分离不会关闭该会话。会话保持打开状态。

这种方法的优点: 您可以从任何其他设备连接到此会话(以防万一您可以SSH电脑)

此方法的缺点: 在您实际存在python解释器之前,此方法不会放弃打开的python会话使用的资源。

I’d like to suggest another way to maintain python session through tmux on linux. you run tmux, attach your self to the session you opened (if not attached after opening it directly). execute python and do whatever you are doing on it. then detach from session. detaching from a tmux session does not close the session. the session remains open.

pros of this method: you can attach to this session from any other device (in case you can ssh your pc)

cons of this method: this method does not relinquish the resources used by the opened python session until you actually exist the python interpreter.


回答 17

要在XUbuntu上保存输入和输出

  1. 在XWindows中,从Xfce终端应用程序运行iPython
  2. Terminal在顶部菜单栏中单击,然后在save contents下拉菜单中查找

我发现这可以保存输入和输出,一直到打开终端时一直返回。这不是ipython特有的,并且可以与ssh会话或从终端窗口运行的其他任务一起使用。

To save input and output on XUbuntu:

  1. In XWindows, run iPython from the Xfce terminal app
  2. click Terminal in the top menu bar and look for save contents in the dropdown

I find this saves the input and output, going all the way back to when I opened the terminal. This is not ipython specific, and would work with ssh sessions or other tasks run from the terminal window.