pypy 與 python的異同

pypy支持的擴(kuò)展模塊(對應(yīng)Python/Modules/中的模塊)

  • pypy支持的內(nèi)建模塊:

    • __builtin__:內(nèi)建模塊,包含一些常用的函數(shù),如abs()等;
    • __pypy__:提供一個(gè)由pypy解析器提供的特殊功能模塊;
    • _ast:抽象句法樹模塊的內(nèi)建模塊,一般直接使用ast模塊;
    • _codecs:注冊表與基類的編解碼器的內(nèi)建模塊,一般直接使用codecs模塊;
    • _collections:容器數(shù)據(jù)類型的內(nèi)建模塊,一般直接使用collections模塊;
    • _continuation
    • _ffi
    • _hashlib:安全散列與消息摘要的內(nèi)建模塊,一般直接使用hashlib模塊;
    • _io:io內(nèi)建模塊,一般直接使用io模塊;
    • _locale:國際化的內(nèi)建模塊,一般直接使用locale模塊;
    • _lsprof:Python分析器的內(nèi)建模塊,一般直接使用lsprof模塊;
    • _md5:md5的內(nèi)建模塊,一般直接使用md5模塊;
    • _minimal_curses:字符顯示的終端處理curses的內(nèi)建模塊,一般直接使用curses模塊,_minimal_curses僅是一個(gè)殘留,只實(shí)現(xiàn)了部分功能,一般使用_curses
    • _multiprocessing:基于進(jìn)程的并行的multiprocessing的內(nèi)建模塊,一般直接使用multiprocessing模塊;
    • _random:生成偽隨機(jī)數(shù)的內(nèi)建模塊,一般直接使用random模塊;
    • _rawffi_rawffi是一個(gè)通過libffi來調(diào)用C的動態(tài)庫方法和創(chuàng)建C對象(數(shù)組或結(jié)構(gòu)體) 的內(nèi)建模塊;
    • _sha:SHA-1的內(nèi)建模塊,在pypy中還有sha模塊,但是一般調(diào)用hashlib,在Ptyhon2.7中sha仍存在,但已經(jīng)是Deprecated,Python3.X中sha已不再使用,一般直接使用hashlib模塊;
    • _socket:Socket的內(nèi)建模塊,一般直接使用socket模塊;
    • _sre:是實(shí)現(xiàn)正則表達(dá)式re大部分功能的內(nèi)建模塊,一般直接使用re模塊;
    • _ssl:TLS/SSL的內(nèi)建模塊,一般直接使用ssl模塊;
    • _warnings:警告控制的內(nèi)建模塊,一般直接使用warnings模塊;
    • _weakref:弱引用的內(nèi)建模塊,一般直接使用weakref模塊;
    • _winreg:Windows注冊表訪問的內(nèi)建模塊,一般直接使用winreg模塊;
    • array:高效數(shù)值數(shù)組的內(nèi)建模塊;
    • binascii:二進(jìn)制碼與ASCII碼間轉(zhuǎn)化的內(nèi)建模塊;
    • bz2:對bzip2壓縮支持的內(nèi)建模塊;
    • cStringIO:對內(nèi)存進(jìn)行文件操作(Read and write strings as files)的C實(shí)現(xiàn)的內(nèi)建模塊;
    • cmath:提供數(shù)學(xué)運(yùn)算的C實(shí)現(xiàn)的內(nèi)建模塊;
    • cpyextcpyext內(nèi)建模塊提供讓pypy使用CPython的擴(kuò)展模塊;
    • crypt:Unix密碼驗(yàn)證的內(nèi)建模塊;
    • errno:標(biāo)準(zhǔn)錯(cuò)誤記號的內(nèi)建模塊;
    • exceptions:異常處理的內(nèi)建模塊;
    • fcntl:系統(tǒng)調(diào)用文件鎖fcntl()和ioctl()的內(nèi)建模塊;
    • gc:垃圾回收的內(nèi)建模塊;
    • imp:訪問import模塊接口的內(nèi)建模塊;
    • itertools:高效循環(huán)的迭代函數(shù)集合的內(nèi)建模塊;
    • marshal:序列化與反序列化的內(nèi)建模塊之一;
    • math:提供數(shù)學(xué)運(yùn)算的內(nèi)建模塊;
    • mmap:內(nèi)存映射文件支持的內(nèi)建模塊;
    • operator:針對函數(shù)標(biāo)準(zhǔn)操作的內(nèi)建模塊;
    • parser:訪問Python解析樹的內(nèi)建模塊;
    • posix:POSIX調(diào)用的內(nèi)建模塊;
    • pyexpat:解析xml的內(nèi)建模塊,一般直接使用xml模塊;;
    • select:提供系統(tǒng)內(nèi)I/O多路復(fù)用的內(nèi)建模塊;
    • struct:將字節(jié)解析為打包的二進(jìn)制數(shù)據(jù)的內(nèi)建模塊;
    • symbol:Python解析樹中的常量的內(nèi)建模塊;
    • sys:系統(tǒng)相關(guān)的參數(shù)與函數(shù)的內(nèi)建模塊;
    • termios:POSIX風(fēng)格的tty控制的內(nèi)建模塊;
    • thread:線程的內(nèi)建模塊;
    • time:時(shí)間日期的內(nèi)建模塊;
    • token:Python解析樹中的常量的內(nèi)建模塊;
    • unicodedata:Unicode字符數(shù)據(jù)庫的內(nèi)建模塊;
    • zipimport:從ZIP歸檔中導(dǎo)入的內(nèi)建模塊;
    • zlib:兼容gzip壓縮的內(nèi)建模塊;
  • 通過純Python重寫的模塊在 lib_pypy/ (部分使用了cffi),比如:ctypescPicklecmathdbmdatetime

垃圾回收機(jī)制(gc)的不同

pypy的垃圾回收機(jī)制實(shí)現(xiàn)并不是使用引用計(jì)數(shù),所以O(shè)bject并不會在不被引用的情況下立即釋放掉。最明顯的影響是,文件(socket等)將不會在離開作用范圍后立馬被關(guān)閉掉。對于寫打開的文件,這可能會導(dǎo)致寫入的數(shù)據(jù)在緩沖區(qū)中一段時(shí)間,是的磁盤上文本被截?cái)嗷蜻€未寫入。還可能導(dǎo)致文件打開數(shù)量超過系統(tǒng)的限制。

如果需要調(diào)試程序中哪里沒有正確關(guān)閉文件,可以使用-X track-resources來運(yùn)行程序。這樣,每當(dāng)GC關(guān)閉一個(gè)文件(或者socket)將會產(chǎn)生一個(gè)ResourceWarning。這個(gè)警告會包含文件(或者socket)打開創(chuàng)建的位置,方便定位問題。

測試代碼:

import time
import gc
print("start")
i = 1
while True:
    print(i)
    i += 1
    open("/data/test.log", "rw")
    if (i % 10) == 0:
        gc.collect()

print("finished")

__del__和弱引用的影響

這個(gè)問題,會影響到__del__方法調(diào)用的準(zhǔn)確時(shí)間,因?yàn)閜ypy的回收是不確定的。這同樣影響到弱引用(weak references),使得弱引用會比預(yù)期的存活時(shí)間長。這導(dǎo)致弱引用代理(由weakref.proxy(object[, callback])返回)的實(shí)用性降低:這使得弱引用代理在目標(biāo)對象的引用失效后仍然能夠被訪問,且會在某個(gè)時(shí)刻突然失效并在下次訪問時(shí)引起ReferenceError錯(cuò)誤。所有使用到弱引用代理的必須小心處理ReferenceError(或者,更好的方法是使用weakref.ref()而不是weakref.proxy())。

測試代碼:

>>>> import weakref
>>>> import gc
>>>> class A(object):
....     def __init__(self):
....         self.test_attr = 100
....         
>>>> def test_func(refrence):
....     print("callback function!")
....   
>>>> a = A()
>>>> 
>>>> x = weakref.proxy(a, test_func)
>>>> x.test_attr
100
>>>> a.test_attr
100
>>>> del a
>>>> 
>>>> x.test_attr
100
>>>> gc.collect()
callback function!
0
>>>> x
<weakproxy at 0x00007f6f19011dc0; dead>
>>>> x.test_attr
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
ReferenceError: weakly referenced object no longer exists
>>>>
>>>> a = A()
>>>> x = weakref.ref(a, test_func)
>>>> print x
<weakref at 0x00007f6f190631a0; to 'A'>
>>>> b = x()
>>>> b.test_attr
100
>>>> del a
>>>> gc.collect()
0
>>>> x
<weakref at 0x00007f6f190631a0; to 'A'>
>>>> b.test_attr
100

某些情況下,由于CPython的引用計(jì)數(shù),弱引用會在它指向的對象之前或之后立即釋放掉,如果在之后釋放掉,那么回調(diào)函數(shù)將會被調(diào)用。但在pypy類似的情況下,對象和弱引用會被認(rèn)為同時(shí)釋放,回調(diào)將不會被調(diào)用。

GC的其他影響

如果一個(gè)對象有__del__方法,在pypy中,__del__被調(diào)用的次數(shù)不會多于1次。但在CPython中,__del__在對象被“復(fù)活”然后“死亡”,__del__可能會被調(diào)用多次。(此處有一段不是很懂,詳見Blog[1] [2].)

GC的差異也會間接的影響到其他方面。比如,pypy代碼中的生成器,將會比CPython中更遲的被垃圾回收。這會影響到yield關(guān)鍵字,如果yieldtry:或者with:中,這會有一個(gè)issue 736

# import gc
def g():
    try:
        yield 1
    finally:
        print "finally"

g().next()
# gc.collect()

這段代碼,在pypy中是沒有打印出finally,在CPython中是有打印的。原因是,在pypy中,finally只有在對象被垃圾回收機(jī)制回收時(shí)才會打印。如果在最后調(diào)用gc.collect(),將能夠打印出來。

使用默認(rèn)的GC(minimark),內(nèi)建函數(shù)id()將會像CPython中那樣工作。但使用其他GC,id()返回的數(shù)字,并不是內(nèi)存地址(因?yàn)橐粋€(gè)對象的地址可能會改變),而且太頻繁調(diào)用將會引起性能問題。

如果程序中有很長的鏈表對象,每一個(gè)中都有指向下一個(gè)的引用,并且都有__del__,這會導(dǎo)致pypy的GC的性能下降。但在其他情況下,pypy的GC性能普遍比CPython好。

__del__還有另外一個(gè)不同的地方,如果往一個(gè)已經(jīng)存在的類中動態(tài)加入__del__,它將不會調(diào)用:

>>>> class A(object):
....     pass
....
>>>> A.__del__ = lambda self: None
__main__:1: RuntimeWarning: a __del__ method added to an existing type will not be called

在pypy中,如果你將__del__動態(tài)綁定給Python的舊式類的對象(對于CPython的新式類也是不工作的),將會得到一個(gè)RuntimeWarning。修改這個(gè)issuse的方法是,在類中定義__del__,僅包含pass(或者其他實(shí)現(xiàn)),再在運(yùn)行時(shí)動態(tài)修改;

CPython會在程序結(jié)束的時(shí)候去自動執(zhí)行gc.collect(),但pypy并不會。

內(nèi)建類型(types)的子類

官方實(shí)現(xiàn)上,CPython對于內(nèi)建類型的子類的重載方法是否會被隱式調(diào)用沒有確定任何規(guī)則。類似的,這些被重載的方法不會被同一個(gè)對象的其他內(nèi)置方法調(diào)用。例如:一個(gè)在dict子類中被重載的__getitem__()將不會被其內(nèi)置函數(shù)get()調(diào)用。

上述的情況在CPython中和PyPy中都是正確的。不同的是,一個(gè)除self以外的另一對象的內(nèi)置方法是否會調(diào)用一個(gè)被重載的方法。這通常在CPython中是不會被調(diào)用的,而在PyPy中則會被調(diào)用。例子:

class D(dict):
    def __getitem__(self, key):
        return "%r from D" % (key,)

class A(object):
    pass

a = A()
a.__dict__ = D()
a.foo = "a's own foo"
print a.foo
# CPython => a's own foo
# PyPy => 'foo' from D

glob = D(foo="base item")
loc = {}
exec "print foo" in glob, loc
# CPython => base item
# PyPy => 'foo' from D

在字典(dictionary)中作為key的自定義類的對象

class X(object):
    pass

def __evil_eq__(self, other):
    print 'hello world'
    return False

def evil(y):
    d = {X(): 1}
    X.__eq__ = __evil_eq__
    d[y] # might trigger a call to __eq__?

在CPython中,__evil_eq__可能會被調(diào)用到,盡管沒有辦法寫出一個(gè)必能重現(xiàn)的例子。這會發(fā)生在y is not xhash(y) == hash(x),同時(shí),hash(x)是在x插入在一個(gè)字典中的時(shí)候計(jì)算的。如果條件滿足,這個(gè)__evil_eq__方法將會被調(diào)用。

PyPy使用一個(gè)特殊的策略來優(yōu)化,一個(gè)用戶自定義類的實(shí)例作為Keys在字典當(dāng)中,且這個(gè)自定義類是沒有重載__hash____eq____cmp__:當(dāng)使用這個(gè)策略的時(shí)候,__eq____cmp__將不會被調(diào)用,而是通過查找id(identity)。所以在上述代碼的情況下,PyPy將能保證__eq__不會被調(diào)用。

在其他情況下(比如,有一個(gè)自定義的__hash____eq__y中),PyPy將會和CPython一樣。

原始數(shù)據(jù)類型的對象標(biāo)識,isid

原始數(shù)據(jù)類型的對象標(biāo)識是根據(jù)值來判斷想等,而不是包裝器的標(biāo)識。這意味著對于一個(gè)任意值的整數(shù)(interger)x來說x + 1 is x + 1總是返回True。這個(gè)規(guī)則適合如下的數(shù)據(jù)類型:

  • int
  • float
  • long
  • complex
  • str(只對空字符串或單個(gè)字符的字符串有效)
  • unicode(只對空字符串或單個(gè)字符的字符串有效)
  • tuple(只對空元組有效)
  • frozenset(只對空的frozenset有效)

這個(gè)改變需要id()也要做出相應(yīng)的改變。id()需要滿足如下情況:x is y <=> id(x) <=> id(y)。因此上述類型的id()將返回一個(gè)從參數(shù)計(jì)算而得到的值,因此可以大于sys.maxint(所以可以是任意長)。

記住,一個(gè)長度大于等于2的字符串,可以相等==,equal)卻不一定相同is,identical)。類似的,盡管x包含一個(gè)元組且x == (2,),但x is (2,)不一定返回True。這個(gè)規(guī)則只適應(yīng)于上述的類型。strunicodetuplefrozenset是在PyPy5.4版本中才適應(yīng)這個(gè)規(guī)則。在5.4之前,盡管x等于?(),但是if x is "?" 或者 if x is ()將會返回False。這個(gè)5.4中的新行為是更為接近CPython,Cpython可以精確的緩存空tuplefirzenset和長度小于等于1的字符串或者unicodes(對于字符串和unicodes并不總是會緩存,當(dāng)大部分情況是)。

對于float,“is”是針對一個(gè)對象的float“位模式”。所以float('nan') is float('nan')在PyPy上返回True,在CPython上返回False,因?yàn)檫@是兩個(gè)對象。但是0.0 is -0.0都返回False,因?yàn)椤拔荒J健辈煌R话愕模?code>float('nan') == float('nan')總是返回False。當(dāng)在容器中使用時(shí)(在列表項(xiàng)或者集合中),判斷相等采用if x is y or x == y(不論在Cpython中或PyPy中)。因此,因?yàn)樗械?code>nans在PyPy中是相同的,所以不能在一個(gè)集合中使用多次,不像CPython(Issuse #1974)

其他

  • hash()方法的隨機(jī)bug在pypy中是忽略的,所以會有以下不同:
Python 3.4.0 (default, Apr 11 2014, 13:05:11) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = "1"
 >>>hash(a)
-7159617557763069555
 >>>exit()

再次運(yùn)行:

Python 3.4.0 (default, Apr 11 2014, 13:05:11) 
[GCC 4.8.2] on linux
Type "help", "copyright", "credits" or "license" for more information.
>>> a = "1"
>>> hash(a)
461546025534110251
>>> exit()

兩次的hash值是不同的,而在pypy中,兩次的hash值是一樣的:

Python 2.7.3 (2.2.1+dfsg-1ubuntu0.3, Sep 30 2015, 15:18:40)
[PyPy 2.2.1 with GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``pypy is more stable than debian''
>>>> a = "1"
>>>> hash(a)
6272018864 
>>>> exit()
Python 2.7.3 (2.2.1+dfsg-1ubuntu0.3, Sep 30 2015, 15:18:40)
[PyPy 2.2.1 with GCC 4.8.4] on linux2
Type "help", "copyright", "credits" or "license" for more information.
And now for something completely different: ``we still have to write software
with a metaspace bubble in it''
>>>> a = "1"
>>>> hash(a)
6272018864
>>>> exit()
  • 不能在一個(gè)類型對象中存儲一個(gè)非字符串的key。例子:
class A(object):
    locals()[42] = 3

# 在PyPy中是不行的
  • sys.setrecursionlimit(n)僅僅是設(shè)置一個(gè)大概的值。這個(gè)通過設(shè)置一個(gè)n * 768bytes的可用棧空間來實(shí)現(xiàn)的。在Linux上,這個(gè)依賴于編譯器的設(shè)置,默認(rèn)值768KB大約能滿足1400次調(diào)用。

  • 因?yàn)閷τ谧值涞膶?shí)現(xiàn)是不同的,每次調(diào)用__hash____eq__所獲的準(zhǔn)確數(shù)字并不相同。由于CPython也沒有一個(gè)準(zhǔn)確的保證,所以不要依賴它。

  • 對于__class__的賦值使用,是基于CPython2.5上的。對于CPython2.6和CPython2.7多個(gè)特性,PyPy仍未支持(如果需要的話,是可以支持的,但在PyPy上需要比CPython2.6/2.7注意更多情況?)。

  • __builtins__的不同:
    在python中有一個(gè)內(nèi)建模塊,中有一些常用函數(shù)。而該模塊在Python啟動后、且沒有執(zhí)行程序員所寫的任何代碼前,Python會首先加載該內(nèi)建函數(shù)到內(nèi)存。

    在pypy和python2.X中,該內(nèi)建模塊是__builtin__,在Python3.X中,該內(nèi)建模塊是builtins

    __builtins__則是對于這個(gè)內(nèi)建模塊的引用。

    無論任何地方要想使用內(nèi)建模塊,都必須在該位置所處的作用域中導(dǎo)入__builtin__(builtins)內(nèi)建模塊;而對于__builtins__卻不用導(dǎo)入,它在任何模塊都直接可見。

    在Python2/3中的主模塊__mian__中,__builtins__是對內(nèi)建模塊__builtin__(builtins)本身的引用,即__builtins__完全等價(jià)于__builtin__(builtins)。

    在Python2/3中的主模塊__mian__中,__builtins__是對內(nèi)建模塊__builtin__.__dict__(builtins.__dict__)的引用,此時(shí)__builtins__的類型是字典。

  • 對于使用無效參數(shù)直接調(diào)用內(nèi)建類型的內(nèi)部“魔法”函數(shù),結(jié)果會有略微的不同。比如:[].__add__(None)(2).__add__(None)在PyPy上都將返回NotImplemented;但在CPython 中,只有(2).__add__(None)會返回NotImplemented[].__add__(None)將引起TypeError。(當(dāng)然,[] + None2 + None無論在PyPy和CPython中都會引起TypeError)。這是內(nèi)部實(shí)現(xiàn)引起的差異,因?yàn)镻yPy沒有內(nèi)部的C語言層面的實(shí)現(xiàn)(Slots?)。

  • 在CPython中,[].__add__是一個(gè)method-wrapper,而list.__add__是一個(gè)slot wrapper。在PyPy中,它們都是一些普通的綁定或未綁定的方法對象。這有時(shí)會使得一些檢查內(nèi)置類型的工具混淆。比如,在標(biāo)準(zhǔn)庫inspect模塊中有一個(gè)ismethod()方法,當(dāng)參數(shù)是綁定或未綁定的方法對象,這個(gè)方法將會返回True,當(dāng)參數(shù)是method-wrapperslot wrapper時(shí),方法返回False。但PyPy并不能區(qū)分它們,所以ismethod([].__add__) == ismethod(list.__add__) == True

  • 在CPython,內(nèi)置類型具有各種方式實(shí)現(xiàn)的屬性。根據(jù)方式,如果試圖寫入(或刪除)一個(gè)只讀(或不可刪除)屬性時(shí),將會引起一個(gè)TypeError或者AttributeError。PyPy試圖在一致性和兼容性之間取舍。這意味著一些小地方將不會和CPython引起相同的異常,比如:del (lambda:None).__closure__

  • 在純Python中,如果寫一個(gè)類class A(object): def f(self): pass,且這個(gè)類有一個(gè)沒有重載f()的子類B,這樣B.f(x)仍然會檢查xB的一個(gè)實(shí)例。在CPython中,如果一個(gè)類型是用C語言實(shí)現(xiàn)的,那個(gè)這個(gè)類型將會有不同的規(guī)則。如果A是采用C語言實(shí)現(xiàn),所有A的實(shí)例將會被B.f(x)接受(實(shí)際上,在這個(gè)情況下B.f is A.f是成立的)。一些代碼可以在CPython上運(yùn)行,但在PyPy上不能:datetime.datetime.strftime(datetime.date.today(), ...)datetime.datedatetime.datetime的父類)。無論如何,正確修復(fù)這個(gè)方法調(diào)用應(yīng)該:datetime.date.today().strftime(...)

  • 在PyPy中,新式類中的__dict__屬性將會返回一個(gè)普通的dict,而不是像CPython中那樣返回一個(gè)dict的代理。改變dict將會改變類型,反之亦然。對于內(nèi)置對象,PyPy將會返回一個(gè)不可修改的dict(但行為和普通的dict類似)。

  • gc模塊的一些方法和屬性會和CPython中有一些略微的不同,比如:gc.enablegc.disable有被支持,但并不是啟用或禁用GC,而是啟用或禁用終結(jié)器(finalizers)的執(zhí)行。

  • 過去的版本中,PyPy在交互模式中啟動時(shí)打印一段來之#pypy IRC的隨機(jī)一行。但在release版本中,這個(gè)行為已經(jīng)被抑制了。但設(shè)置一個(gè)PYPY_IRC_TOPIC環(huán)境變量將會啟動這個(gè)行為。要注意使用到的軟件包完全禁用這個(gè)功能。

  • PyPy的readline模塊是完全重寫的,它并不是GUN的readline。它添加了多行的支持(詳見multiline_input())。但另一方面parse_and_bind()的調(diào)用會被忽略(issue #2072)。

  • sys.getsizeof()總會引起TypeError。這是因?yàn)榇撕瘮?shù)的內(nèi)存分析器很有可能給出與PyPy實(shí)際上不同的結(jié)果。讓sys.getsizeof()返回一個(gè)數(shù)字(需要足夠的工作)是可行的,但是這個(gè)數(shù)字有可能不能準(zhǔn)確代表著這個(gè)對象使用的內(nèi)存大小。在于系統(tǒng)其余部分(?)隔絕的情況下,這個(gè)數(shù)字甚至反應(yīng)不了一個(gè)對象使用的內(nèi)存大小。比如一個(gè)實(shí)例有maps,這個(gè)maps會經(jīng)常在許多實(shí)例之間共享。在這種情況下,這個(gè)maps會被sys.getsizeof()的實(shí)現(xiàn)忽略,但在某些情況下,如果這個(gè)maps有著很多唯一的實(shí)例,那么它的內(nèi)存開銷是很重要的。相反的,即使是不同的對象,相等的字符串可以共享它們的內(nèi)部數(shù)據(jù),或者一些空的container會一直共享它們部分的內(nèi)存,直到它們不再為空。更奇怪的是,一些list會在你對它進(jìn)行讀操作時(shí)創(chuàng)建一些對象;如果嘗試估計(jì)range(10**6)的內(nèi)存大小綜合,這個(gè)操作自身會創(chuàng)建一百萬個(gè)整型對象,但這些對象在開始時(shí)不存在的。在CPython中也會有類似的問題,只是少一些。以上就是不實(shí)現(xiàn)sys.getsizeof()的原因。

  • timeit模塊在PyPy中的表現(xiàn)會有所不同:它但打印的時(shí)平均時(shí)間和標(biāo)準(zhǔn)差,而不是CPython中的最小值,因?yàn)樽钚≈低ǔJ怯姓`差的。

  • sysconfig模塊中的get_config_vars方法和distutil.sysconfig這兩個(gè)是未完成的。在POSIX平臺,CPython在Makefile中獲取配置變量來編譯生成解析器。PyPy也需要在編譯的期間生成這些值,但還未完成。

  • "%d" % d"%x" % x等類似的結(jié)構(gòu)中,當(dāng)x是一個(gè)long的子類的實(shí)例時(shí),并且這個(gè)子類重載了__str____hex____oct__這幾個(gè)特殊方法時(shí):PyPy將不會調(diào)用這些特殊方法;CPython是會的,但僅限于long的子類,不包括int。CPython的這些表現(xiàn)是很混亂的:比如,對于%x應(yīng)該調(diào)用__hex__()__hex__()的功能是支持返回一個(gè)類似-0x123L的字符串了;然后%x會去掉0x和最后的L,保留其余部分。如果重載的__hex__()返回一個(gè)格式不正確的字符串,那么將會獲得一個(gè)異常(在CPython2.7.13之前會之前crash)。

  • 在CPython2.7.13中,sqlite模塊有一個(gè)更新,當(dāng)有一個(gè)提交時(shí)它將不再重置所有的游標(biāo)(cursors)。這會使得PyPy中有一些麻煩(CPython也可能會有),所以PyPy并沒有移植這個(gè)更改:http://bugs.python.org/issue29006

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

推薦閱讀更多精彩內(nèi)容

  • 1.元類 1.1.1類也是對象 在大多數(shù)編程語言中,類就是一組用來描述如何生成一個(gè)對象的代碼段。在Python中這...
    TENG書閱讀 1,306評論 0 3
  • 本節(jié)內(nèi)容 Python介紹 發(fā)展史 Python 2 or 3? 安裝 Hello World程序 變量 用戶輸入...
    小小不懂11閱讀 3,446評論 2 30
  • 文/Bruce.Liu1 1.Python前世今生 1.1.Python歷史 Python的創(chuàng)始人: Guido ...
    BruceLiu1閱讀 11,866評論 3 119
  • 連載十二 出乎意料 1. 素碧此刻才發(fā)覺胡敦厚是一本正經(jīng)的,終于說了點(diǎn)人話,其余的時(shí)候他都是一個(gè)不折不扣的痞子貨。...
    周琦橞閱讀 370評論 8 7
  • 25歲時(shí),我放棄原有的3線小城市工作,來到上海。不能說是為了夢想,只能說是為了實(shí)現(xiàn)自我價(jià)值。工作內(nèi)容類似于售后客服...
    優(yōu)的世界閱讀 360評論 0 0