Vad är nytt i Python 2.5¶
- Författare:
A.M. Kuchling
Den här artikeln förklarar de nya funktionerna i Python 2.5. Den slutliga utgåvan av Python 2.5 är planerad till augusti 2006; PEP 356 beskriver det planerade utgivningsschemat. Python 2.5 släpptes den 19 september 2006.
Förändringarna i Python 2.5 är en intressant blandning av språk- och biblioteksförbättringar. Biblioteksförbättringarna kommer att vara viktigare för Pythons användargrupp, tror jag, eftersom flera mycket användbara paket har lagts till. Bland de nya modulerna finns ElementTree för XML-bearbetning (xml.etree
), databasmodulen SQLite (sqlite
) och modulen ctypes
för anrop av C-funktioner.
De språkliga förändringarna är av medelstor betydelse. Några trevliga nya funktioner har lagts till, men de flesta av dem är inte funktioner som du kommer att använda varje dag. Villkorliga uttryck har äntligen lagts till i språket med hjälp av en ny syntax; se avsnitt PEP 308: Villkorliga uttryck. Den nya ’with
’-satsen gör det enklare att skriva uppstädningskod (avsnitt PEP 343: Uttalandet ”med). Värden kan nu skickas in i generatorer (sektion PEP 342: Nya generatorfunktioner). Importer är nu synliga som antingen absoluta eller relativa (sektion PEP 328: Absolut och relativ import). Vissa hörnfall av undantagshantering hanteras bättre (sektion PEP 341: Unifierad try/except/finally). Alla dessa förbättringar är värdefulla, men de är förbättringar av en eller annan specifik språkfunktion; ingen av dem är breda modifieringar av Pythons semantik.
Förutom språk- och bibliotekstilläggen gjordes andra förbättringar och buggfixar i hela källträdet. En sökning genom SVN-ändringsloggarna visar att det fanns 353 korrigeringar som tillämpades och 458 buggar fixade mellan Python 2.4 och 2.5. (Båda siffrorna är sannolikt underskattningar)
Den här artikeln försöker inte vara en fullständig specifikation av de nya funktionerna, utan ändringarna presenteras kortfattat med hjälp av användbara exempel. För fullständiga detaljer bör du alltid hänvisa till dokumentationen för Python 2.5 på https://docs.python.org. Om du vill förstå den fullständiga implementeringen och designrationaliteten, se PEP för en viss ny funktion.
Kommentarer, förslag och felrapporter för detta dokument är välkomna; skicka dem till författaren eller öppna en bugg i Pythons buggspårare.
PEP 308: Villkorliga uttryck¶
Under lång tid har det efterfrågats ett sätt att skriva villkorliga uttryck, dvs. uttryck som returnerar värde A eller värde B beroende på om ett booleskt värde är sant eller falskt. Med ett villkorligt uttryck kan du skriva en enda assignment-sats som har samma effekt som följande:
om villkor:
x = sant_värde
annat:
x = falskt_värde
Det har varit oändliga tråkiga diskussioner om syntax på både python-dev och comp.lang.python. En omröstning hölls till och med som visade att majoriteten av de röstande ville ha villkorliga uttryck i någon form, men det fanns ingen syntax som föredrogs av en klar majoritet. Bland kandidaterna fanns C:s cond ? true_v : false_v
, if cond then true_v else false_v
och 16 andra varianter.
Guido van Rossum valde till slut en överraskande syntax:
x = sant_värde if villkor else falskt_värde
Utvärderingen är fortfarande lat som i befintliga booleska uttryck, så utvärderingsordningen hoppar runt lite. Uttrycket condition i mitten utvärderas först, och uttrycket true_value utvärderas endast om villkoret var sant. På samma sätt utvärderas false_value-uttrycket endast om villkoret är falskt.
Syntaxen kan verka konstig och bakvänd; varför placeras villkoret i mitt av uttrycket och inte längst fram som i C:s c ? x : y
? Beslutet kontrollerades genom att tillämpa den nya syntaxen på modulerna i standardbiblioteket och se hur den resulterande koden lästes. I många fall där ett villkorligt uttryck används verkar ett värde vara det ”vanliga fallet” och ett värde vara ett ”undantagsfall”, som bara används vid sällsynta tillfällen när villkoret inte uppfylls. Den villkorliga syntaxen gör detta mönster lite mer uppenbart:
innehåll = ((doc + '\n') if doc else '')
Jag läser ovanstående uttalande som ”här contents tilldelas vanligtvis ett värde av doc+'\n'
; ibland doc är tom, i vilket specialfall en tom sträng returneras.” Jag tvivlar på att jag kommer att använda villkorliga uttryck mycket ofta där det inte finns ett tydligt vanligt och ovanligt fall.
Det diskuterades om språket skulle kräva att villkorliga uttryck omgärdas av parenteser. Beslutet blev att inte kräva parenteser i Pythonspråkets grammatik, men som en stilfråga tycker jag att man alltid ska använda dem. Tänk på dessa två uttalanden:
# Första versionen -- inga parenteser
level = 1 if logging else 0
# Andra versionen -- med parenteser
nivå = (1 om loggning annars 0)
I den första versionen tror jag att läsarens öga kan gruppera satsen i ”nivå = 1”, ”if loggning”, ”else 0”, och tro att villkoret avgör om tilldelningen till nivå utförs. Den andra versionen läser bättre, enligt min mening, eftersom den gör det tydligt att tilldelningen alltid utförs och att valet görs mellan två värden.
Ett annat skäl till att inkludera parenteserna: några udda kombinationer av listförståelser och lambdas kan se ut som felaktiga villkorliga uttryck. Se PEP 308 för några exempel. Om du sätter parenteser runt dina villkorliga uttryck kommer du inte att stöta på det här fallet.
Se även
- PEP 308 - Villkorliga uttryck
PEP skriven av Guido van Rossum och Raymond D. Hettinger; implementerad av Thomas Wouters.
PEP 309: Tillämpning av partiell funktion¶
Modulen functools
är avsedd att innehålla verktyg för programmering i funktionell stil.
Ett användbart verktyg i den här modulen är funktionen partial()
. För program som är skrivna i en funktionell stil vill du ibland konstruera varianter av befintliga funktioner som har några av parametrarna ifyllda. Tänk på en Python-funktion f(a, b, c)
; du kan skapa en ny funktion g(b, c)
som är likvärdig med f(1, b, c)
. Detta kallas ”partiell funktionstillämpning”.
partial()
tar argumenten (function, arg1, arg2, ... kwarg1=värde1, kwarg2=värde2)
. Det resulterande objektet är anropsbart, så du kan bara anropa det för att anropa function med de ifyllda argumenten.
Här är ett litet men realistiskt exempel:
import functools
def log (message, subsystem):
"Write the contents of 'message' to the specified subsystem."
print '%s: %s' % (subsystem, message)
...
server_log = functools.partial(log, subsystem='server')
server_log('Unable to open socket')
Här är ett annat exempel, från ett program som använder PyGTK. Här konstrueras en kontextkänslig popup-meny dynamiskt. Callbacken som tillhandahålls för menyalternativet är en delvis tillämpad version av metoden open_item()
, där det första argumentet har tillhandahållits.
...
klass Applikation:
def open_item(self, path):
...
def init (self):
open_func = functools.partial(self.open_item, item_path)
popup_menu.append( ("Öppna", open_func, 1) )
En annan funktion i modulen functools
är funktionen update_wrapper(wrapper, wrapped)
som hjälper dig att skriva välskötta dekoratorer. update_wrapper()
kopierar attributen namn, modul och docstring till en wrapper-funktion så att spårningar inuti den omslutna funktionen blir lättare att förstå. Du kan till exempel skriva:
def my_decorator(f):
def wrapper(*args, **kwds):
print 'Anropar dekorerad funktion'
return f(*args, **kwds)
functools.update_wrapper(wrapper, f)
returnerar omslag
wraps()
är en dekorator som kan användas i dina egna dekoratorer för att kopiera den omslutna funktionens information. En alternativ version av det tidigare exemplet skulle vara:
def min_dekoratör(f):
@functools.wraps(f)
def wrapper(*args, **kwds):
print 'Anropar dekorerad funktion'
returnera f(*args, **kwds)
returnera omslag
Se även
- PEP 309 - Tillämpning av partiell funktion
PEP föreslagen och skriven av Peter Harris; implementerad av Hye-Shik Chang och Nick Coghlan, med anpassningar av Raymond Hettinger.
PEP 314: Metadata för Python-programvarupaket v1.1¶
Ett enkelt stöd för beroenden har lagts till i Distutils. Funktionen setup()
har nu nyckelordsparametrarna requires
, provides
och obsoletes
. När du bygger en källdistribution med kommandot sdist
kommer beroendeinformationen att registreras i filen PKG-INFO
.
En annan ny nyckelordsparameter är download_url
, som bör ställas in på en URL för paketets källkod. Detta innebär att det nu är möjligt att slå upp en post i paketindexet, bestämma beroendena för ett paket och hämta de paket som krävs:
VERSION = '1.0'
setup(name='PyPackage',
version=VERSION,
kräver=['numarray', 'zlib (>=1.1.4)'],
obsoletes=['OldPackage']
download_url=('http://www.example.com/pypackage/dist/pkg-%s.tar.gz'
% VERSION),
)
En annan ny förbättring av Python-paketindexet på https://pypi.org är lagring av käll- och binärarkiv för ett paket. Det nya kommandot upload Distutils laddar upp ett paket till arkivet.
Innan ett paket kan laddas upp måste du kunna bygga en distribution med hjälp av kommandot sdist Distutils. När det fungerar kan du köra python setup.py upload
för att lägga till ditt paket i PyPI-arkivet. Eventuellt kan du GPG-signera paketet genom att ange alternativen --sign
och --identity
.
Paketuppladdningen genomfördes av Martin von Löwis och Richard Jones.
Se även
- PEP 314 - Metadata för Python-programvarupaket v1.1
PEP föreslogs och skrevs av A.M. Kuchling, Richard Jones och Fred Drake; implementerades av Richard Jones och Fred Drake.
PEP 328: Absolut och relativ import¶
Den enklare delen av PEP 328 implementerades i Python 2.4: parenteser kan nu användas för att omsluta de namn som importeras från en modul med hjälp av from ... import ...
-satsen, vilket gör det enklare att importera många olika namn.
Den mer komplicerade delen har implementerats i Python 2.5: import av en modul kan specificeras för att använda absolut eller paketrelativ import. Planen är att gå mot att göra absolut import till standard i framtida versioner av Python.
Låt oss säga att du har en paketkatalog så här:
pkg/
pkg/__init__.py
pkg/main.py
pkg/string.py
Detta definierar ett paket med namnet pkg
som innehåller undermodulerna pkg.main
och pkg.string
.
Betrakta koden i modulen main.py
. Vad händer om den exekverar satsen import string
? I Python 2.4 och tidigare letar den först i paketets katalog för att utföra en relativ import, hittar pkg/string.py
, importerar innehållet i den filen som modulen pkg.string
, och den modulen är bunden till namnet string
i modulen pkg.main
:s namnrymd.
Det är bra om pkg.string
var vad du ville ha. Men vad händer om du vill ha Pythons standardmodul string
? Det finns inget rent sätt att ignorera pkg.string
och leta efter standardmodulen; i allmänhet måste du titta på innehållet i sys.modules
, vilket är något orent. Holger Krekels py.std
-paket ger ett snyggare sätt att utföra import från standardbiblioteket, import py; py.std.string.join()
, men det paketet är inte tillgängligt på alla Python-installationer.
Att läsa kod som förlitar sig på relativ import är också mindre tydligt, eftersom en läsare kan bli förvirrad över vilken modul, string
eller pkg.string
, som är avsedd att användas. Python-användare lärde sig snart att inte duplicera namnen på standardbiblioteksmoduler i namnen på sina pakets undermoduler, men du kan inte skydda dig mot att din undermoduls namn används för en ny modul som läggs till i en framtida version av Python.
I Python 2.5 kan du byta import
beteende till absolut import med hjälp av ett from __future__ import absolute_import
direktiv. Detta absoluta importbeteende kommer att bli standard i en framtida version (förmodligen Python 2.7). När absolut import är standard, kommer import string
alltid att hitta standardbibliotekets version. Det föreslås att användare ska börja använda absolut import så mycket som möjligt, så det är att föredra att börja skriva from pkg import string
i din kod.
Relativ import är fortfarande möjlig genom att lägga till en inledande punkt i modulnamnet när du använder formuläret from ... import
:
# Import names from pkg.string
from .string import name1, name2
# Import pkg.string
from . import string
Detta importerar modulen string
relativt det aktuella paketet, så i pkg.main
kommer detta att importera namn1 och namn2 från pkg.string
. Ytterligare inledande punkter utför den relativa importen med början från det aktuella paketets överordnade enhet. Till exempel kan kod i modulen A.B.C
göra:
from . import D # Import A.B.D
från .. import E # Import A.E
från ..F import G # Import A.F.G
Ledande punkter kan inte användas med formen import modname
av import-satsen, endast med formen from ... import
.
Se även
- PEP 328 - Import: Flera rader och absolut/relativ
PEP skriven av Aahz; implementerad av Thomas Wouters.
- https://pylib.readthedocs.io/
Py-biblioteket av Holger Krekel, som innehåller paketet
py.std
.
PEP 338: Exekvera moduler som skript¶
Omkopplaren -m
som lades till i Python 2.4 för att exekvera en modul som ett skript har fått några fler förmågor. Istället för att implementeras i C-kod inuti Python-tolken använder bytet nu en implementering i en ny modul, runpy
.
Modulen runpy
implementerar en mer sofistikerad importmekanism så att det nu är möjligt att köra moduler i ett paket som pychecker.checker
. Modulen stöder även alternativa importmekanismer som modulen zipimport
. Det innebär att du kan lägga till sökvägen till ett .zip-arkiv i sys.path
och sedan använda -m
för att exekvera kod från arkivet.
Se även
- PEP 338 - Exekvera moduler som skript
PEP skrivet och genomfört av Nick Coghlan.
PEP 341: Unifierad try/except/finally¶
Fram till Python 2.5 fanns try
-satsen i två varianter. Du kan använda ett finally
-block för att säkerställa att koden alltid körs, eller ett eller flera except
-block för att fånga specifika undantag. Det gick inte att kombinera både except
-block och ett finally
-block, eftersom det var komplicerat att generera rätt bytecode för den kombinerade versionen och det var oklart vad semantiken i den kombinerade satsen skulle vara.
Guido van Rossum tillbringade en del tid med att arbeta med Java, som stöder motsvarande kombination av except
-block och ett finally
-block, och detta klargjorde vad uttalandet skulle betyda. I Python 2.5 kan man nu skriva:
försök:
block-1 ...
utom Exception1:
hanterare-1 ...
utom Undantag2:
handläggare-2 ...
else:
else-block
slutligen:
final-block
Koden i block-1 exekveras. Om koden ger upphov till ett undantag, testas de olika except
-blocken: om undantaget är av klass Exception1
, utförs handler-1; annars om det är av klass Exception2
, utförs handler-2, och så vidare. Om inget undantag uppstår körs else-blocket.
Oavsett vad som hänt tidigare körs final-block när kodblocket är färdigt och eventuella undantag har hanterats. Även om det uppstår ett fel i en undantagshanterare eller i else-blocket och ett nytt undantag uppstår, körs koden i final-blocket ändå.
Se även
- PEP 341 - Förenande av try-except och try-finally
PEP skriven av Georg Brandl; implementation av Thomas Lee.
PEP 342: Nya generatorfunktioner¶
Python 2.5 lägger till ett enkelt sätt att skicka värden in en generator. Som introducerades i Python 2.3 producerar generatorer bara utdata; när en generators kod har åberopats för att skapa en iterator fanns det inget sätt att skicka någon ny information till funktionen när dess exekvering återupptogs. Ibland skulle det vara användbart att kunna skicka in lite information. Hackiga lösningar på detta inkluderar att låta generatorns kod titta på en global variabel och sedan ändra den globala variabelns värde, eller skicka in något mutabelt objekt som anroparna sedan ändrar.
För att friska upp minnet av grundläggande generatorer följer här ett enkelt exempel:
def räknare (max):
i = 0
medan i < maximum:
ge i
i += 1
När du anropar counter(10)
blir resultatet en iterator som returnerar värdena från 0 upp till 9. När du stöter på yield
-satsen returnerar iteratorn det angivna värdet och avbryter funktionens exekvering, varvid de lokala variablerna bevaras. Exekveringen återupptas vid följande anrop till iteratorns next()
-metod, som tar vid efter yield
-satsen.
I Python 2.3 var yield
ett uttalande; det returnerade inte något värde. I 2.5 är yield
nu ett uttryck som returnerar ett värde som kan tilldelas en variabel eller på annat sätt användas:
val = (avkastning i)
Jag rekommenderar att du alltid sätter parenteser runt ett yield
-uttryck när du gör något med det returnerade värdet, som i exemplet ovan. Parenteserna är inte alltid nödvändiga, men det är lättare att alltid lägga till dem istället för att behöva komma ihåg när de behövs.
(PEP 342 förklarar de exakta reglerna, som är att ett yield
-uttryck alltid måste vara inom parentes utom när det förekommer i toppnivåuttrycket på höger sida av en tilldelning. Det betyder att du kan skriva val = yield i
men måste använda parenteser när det finns en operation, som i val = (yield i) + 12
)
Värden skickas till en generator genom att anropa dess metod send(value)
. Generatorns kod återupptas sedan och uttrycket yield
returnerar det angivna värdet. Om den vanliga metoden next()
anropas returnerar yield
None
.
Här är det föregående exemplet, modifierat så att det går att ändra värdet på den interna räknaren:
def räknare (max):
i = 0
medan i < maximum:
val = (avkastning i)
# Om värde anges, ändra räknaren
om val inte är None:
i = val
i annat fall
i += 1
Och här är ett exempel på hur man ändrar räknaren:
>>> it = counter(10)
>>> print it.next()
0
>>> print it.next()
1
>>> print it.send(8)
8
>>> print it.next()
9
>>> print it.next()
Traceback (most recent call last):
File "t.py", line 15, in ?
print it.next()
StopIteration
yield
kommer vanligtvis att returnera None
, så du bör alltid kontrollera för detta fall. Använd inte bara dess värde i uttryck om du inte är säker på att metoden send()
kommer att vara den enda metod som används för att återuppta din generatorfunktion.
Förutom send()
finns det två andra nya metoder för generatorer:
throw(type, value=None, traceback=None)
används för att skapa ett undantag inuti generatorn; undantaget skapas avyield
-uttrycket där generatorns exekvering pausas.close()
ger upphov till ett nyttGeneratorExit
undantag inuti generatorn för att avsluta iterationen. När detta undantag tas emot måste generatorns kod antingen ge upphov tillGeneratorExit
ellerStopIteration
. Att fånga upp undantagetGeneratorExit
och returnera ett värde är olagligt och kommer att utlösa ettRuntimeError
; om funktionen ger upphov till något annat undantag, kommer det undantaget att spridas till den som anropar.close()
kommer också att anropas av Pythons skräpsamlare när generatorn är skräpsamlad.Om du behöver köra upprensningskod när en
GeneratorExit
inträffar föreslår jag att du använder entry: ... finally:
svit istället för att fångaGeneratorExit
.
Den sammantagna effekten av dessa förändringar är att generatorer förvandlas från enkelriktade producenter av information till både producenter och konsumenter.
Generatorer blir också koroutiner, en mer generaliserad form av subrutiner. Subrutiner startas vid en punkt och avslutas vid en annan punkt (toppen av funktionen och ett return
-slutsats), men coroutines kan startas, avslutas och återupptas vid många olika punkter (yield
-slutsatserna). Vi måste räkna ut mönster för att använda coroutines effektivt i Python.
Tillägget av metoden close()
har en bieffekt som inte är uppenbar. close()
anropas när en generator sopas bort, vilket innebär att generatorns kod får en sista chans att köras innan generatorn förstörs. Denna sista chans innebär att try...finally
-satser i generatorer nu garanterat fungerar; finally
-klausulen får nu alltid en chans att köras. Den syntaktiska begränsningen som innebar att man inte kunde blanda yield
-satser med en try...finally
-svit har därför tagits bort. Detta verkar vara en mindre språklig detalj, men att använda generatorer och try...finally
är faktiskt nödvändigt för att implementera with
-satsen som beskrivs i PEP 343. Jag kommer att titta på denna nya sats i nästa avsnitt.
En annan ännu mer esoterisk effekt av denna ändring: tidigare var attributet gi_frame
för en generator alltid ett ramobjekt. Det är nu möjligt för gi_frame
att vara None
när generatorn har uttömts.
Se även
- PEP 342 - Coroutines via förbättrade generatorer
PEP skriven av Guido van Rossum och Phillip J. Eby; implementerad av Phillip J. Eby. Innehåller exempel på några mer avancerade användningar av generatorer som coroutines.
Tidigare versioner av dessa funktioner föreslogs i PEP 288 av Raymond Hettinger och PEP 325 av Samuele Pedroni.
- https://en.wikipedia.org/wiki/Coroutine
Wikipedia-artikeln om coroutines.
- https://web.archive.org/web/20160321211320/http://www.sidhe.org/~dan/blog/archives/000178.html
En förklaring av coroutines från en Perl-synvinkel, skriven av Dan Sugalski.
PEP 343: Uttalandet ”med¶
Satsen ’with
’ förtydligar kod som tidigare skulle använda try...finally
-block för att säkerställa att uppstädningskoden körs. I det här avsnittet diskuterar jag uttalandet som det vanligtvis kommer att användas. I nästa avsnitt undersöker jag implementeringsdetaljerna och visar hur man skriver objekt som kan användas med den här satsen.
’with
’ är en ny kontrollflödesstruktur vars grundstruktur är:
med uttryck [som variabel]:
med-blockera
Uttrycket utvärderas och bör resultera i ett objekt som stöder protokollet för kontexthantering (dvs. har metoderna __enter__()
och __exit__()
).
Objektets __enter__()
anropas innan with-block exekveras och kan därför köra installationskod. Den kan också returnera ett värde som är bundet till namnet variable, om det anges. (Observera noga att variable inte tilldelas resultatet av expression)
Efter att with-blocket har exekverats anropas objektets metod __exit__()
, även om blocket gav upphov till ett undantag, och kan därför köra uppstädningskod.
För att aktivera uttalandet i Python 2.5 måste du lägga till följande direktiv i din modul:
from __future__ import med_uttalande
Uttalandet kommer alltid att vara aktiverat i Python 2.6.
Vissa standard Python-objekt har nu stöd för kontexthanteringsprotokollet och kan användas med ’with
’. Filobjekt är ett exempel:
med open('/etc/passwd', 'r') som f:
för rad i f:
skriv ut rad
... mer bearbetningskod ...
Efter att denna sats har exekverats kommer filobjektet i f att ha stängts automatiskt, även om for
-loopen gjorde ett undantag halvvägs genom blocket.
Anteckning
I det här fallet är f samma objekt som skapades av open()
, eftersom __enter__()
returnerar self.
Modulen threading
:s lås och villkorvariabler stöder också ’with
’-satsen:
lock = threading.Lock()
med lock:
# Kritisk del av koden
...
Låset förvärvas innan blocket exekveras och släpps alltid när blocket är klart.
Den nya funktionen localcontext()
i modulen decimal
gör det enkelt att spara och återställa den aktuella decimalkontexten, som innehåller önskad precision och avrundningsegenskaper för beräkningar:
från decimal importera Decimal, Context, localcontext
# Visar med standardprecision på 28 siffror
v = Decimal('578')
print v.sqrt()
med localcontext(Context(prec=16)):
# All kod i detta block använder en precision på 16 siffror.
# Den ursprungliga kontexten återställs när blocket avslutas.
skriv ut v.sqrt()
Skriva för kontextansvariga¶
Under huven är ’with
’-satsen ganska komplicerad. De flesta människor kommer bara att använda ’with
’ i samband med befintliga objekt och behöver inte känna till dessa detaljer, så du kan hoppa över resten av det här avsnittet om du vill. Författare till nya objekt kommer att behöva förstå detaljerna i den underliggande implementationen och bör fortsätta läsa.
En förklaring på hög nivå av protokollet för kontexthantering är:
Uttrycket utvärderas och bör resultera i ett objekt som kallas ”context manager”. Kontexthanteraren måste ha metoderna
__enter__()
och__exit__()
.Kontexthanterarens metod
__enter__()
anropas. Det värde som returneras tilldelas VAR. Om ingen'as VAR'
-klausul finns, kasseras värdet helt enkelt.Koden i BLOCK utförs.
Om BLOCK ger upphov till ett undantag anropas
__exit__(type, value, traceback)
med undantagsdetaljerna, samma värden som returneras avsys.exc_info()
. Metodens returvärde styr om undantaget ska tas upp igen: alla falska värden tar upp undantaget igen, ochTrue
resulterar i att det undertrycks. Du kommer bara sällan att vilja undertrycka undantaget, för om du gör det kommer författaren till koden som innehåller ’with
’-uttalandet aldrig att inse att något gick fel.Om BLOCK inte gav upphov till ett undantag anropas fortfarande metoden
__exit__()
, men type, value och traceback är allaNone
.
Låt oss tänka igenom ett exempel. Jag kommer inte att presentera detaljerad kod utan bara skissa på de metoder som krävs för en databas som stöder transaktioner.
(För den som inte är bekant med databasterminologi: en uppsättning ändringar i databasen grupperas i en transaktion. Transaktioner kan antingen bekräftas, vilket innebär att alla ändringar skrivs in i databasen, eller rullas tillbaka, vilket innebär att alla ändringar tas bort och att databasen är oförändrad. Se en databasbok för mer information)
Låt oss anta att det finns ett objekt som representerar en databasanslutning. Vårt mål kommer att vara att låta användaren skriva kod som denna:
db_connection = Databasanslutning()
med db_connection som cursor:
cursor.execute('insert into ...')
cursor.execute('ta bort från ...')
# ... fler operationer ...
Transaktionen bör genomföras om koden i blocket körs felfritt eller rullas tillbaka om det finns ett undantag. Här är det grundläggande gränssnittet för DatabaseConnection
som jag kommer att anta:
klass DatabaseConnection:
# Databasgränssnitt
def cursor (self):
"Returnerar ett cursor-objekt och startar en ny transaktion"
def commit (self):
"Commitar aktuell transaktion"
def rollback (self):
"Rullar tillbaka aktuell transaktion"
Metoden __enter__()
är ganska enkel, det räcker med att starta en ny transaktion. För den här applikationen skulle det resulterande markörobjektet vara ett användbart resultat, så metoden returnerar det. Användaren kan sedan lägga till as cursor
i sin ’with
’-sats för att binda markören till ett variabelnamn.
klass DatabaseConnection:
...
def __enter__ (self):
# Kod för att starta en ny transaktion
cursor = self.cursor()
returnera cursor
Metoden __exit__()
är den mest komplicerade eftersom det är där det mesta av arbetet måste göras. Metoden måste kontrollera om ett undantag inträffade. Om det inte inträffade något undantag genomförs transaktionen. Transaktionen rullas tillbaka om det inträffade ett undantag.
I koden nedan kommer exekveringen bara att falla av i slutet av funktionen och returnera standardvärdet None
. None
är falskt, så undantaget kommer att återkallas automatiskt. Om du vill kan du vara mer explicit och lägga till en return
-sats på den markerade platsen.
klass DatabaseConnection:
...
def __exit__ (self, type, value, tb):
om tb är None:
# Inget undantag, så commit
self.commit()
else:
# Undantag inträffade, så rollback.
self.rollback()
# return False
Modulen contextlib¶
Den nya modulen contextlib
innehåller några funktioner och en dekorator som är användbara för att skriva objekt som kan användas med ’with
’.
Dekoratorn heter contextmanager()
och gör att du kan skriva en enda generatorfunktion istället för att definiera en ny klass. Generatorn ska ge exakt ett värde. Koden fram till yield
kommer att exekveras som __enter__()
-metoden, och värdet som genereras kommer att vara metodens returvärde som kommer att bindas till variabeln i ’with
’-satsens as
-klausul, om någon. Koden efter yield
kommer att exekveras i metoden __exit__()
. Alla undantag som uppstår i blocket kommer att uppstå i yield
-satsen.
Vårt databasexempel från föregående avsnitt kan skrivas med hjälp av denna dekorator som:
från contextlib import contextmanager
@kontexthanterare
def db_transaction (anslutning):
cursor = anslutning.cursor()
försök:
ge cursor
except:
anslutning.rollback()
höja
else:
anslutning.commit()
db = Databasanslutning()
med db_transaction(db) som cursor:
...
Modulen contextlib
har också en funktion nested(mgr1, mgr2, ...)
som kombinerar ett antal kontexthanterare så att du inte behöver skriva nästlade ’with
’-satser. I det här exemplet startar en enda ’with
’-sats både en databastransaktion och förvärvar ett trådlås:
lock = threading.Lock()
med nested (db_transaction(db), lock) som (cursor, locked):
...
Slutligen returnerar funktionen closing(object)
object så att det kan bindas till en variabel och anropar object.close
i slutet av blocket.
import urllib, sys
from contextlib import closing
with closing(urllib.urlopen('http://www.yahoo.com')) as f:
for line in f:
sys.stdout.write(line)
Se även
- PEP 343 - Uttalandet ”med”
PEP skriven av Guido van Rossum och Nick Coghlan; implementerad av Mike Bland, Guido van Rossum och Neal Norwitz. PEP:n visar koden som genereras för en ’
with
’-sats, vilket kan vara till hjälp för att lära sig hur satsen fungerar.
Dokumentationen för modulen contextlib
.
PEP 352: Undantag som klasser av ny typ¶
Undantagsklasser kan nu vara klasser av ny typ, inte bara klassiska klasser, och den inbyggda klassen Exception
och alla de inbyggda standardundantagen (NameError
, ValueError
, etc.) är nu klasser av ny typ.
Arvshierarkin för undantag har omarrangerats en aning. I 2.5 är arvsförhållandena:
BaseException # Nytt i Python 2.5
|- KeyboardInterrupt
|- SystemExit
|- Undantag
|- (alla andra nuvarande inbyggda undantag)
Denna omorganisering gjordes eftersom människor ofta vill fånga alla undantag som indikerar programfel. KeyboardInterrupt
och SystemExit
är dock inte fel, och representerar vanligtvis en explicit åtgärd som att användaren trycker på Control-C eller att koden anropar sys.exit()
. En ren except:
fångar alla undantag, så du behöver ofta lista KeyboardInterrupt
och SystemExit
för att kunna ta upp dem igen. Det vanliga mönstret är:
försök:
...
except (KeyboardInterrupt, SystemExit):
höja
utom:
# Logga fel ...
# Fortsätt köra programmet...
I Python 2.5 kan du nu skriva except Exception
för att uppnå samma resultat, fånga alla undantag som vanligtvis indikerar fel men lämna KeyboardInterrupt
och SystemExit
ifred. Precis som i tidigare versioner fångar en ren except:
fortfarande alla undantag.
Målet för Python 3.0 är att kräva att alla klasser som tas upp som undantag härstammar från BaseException
eller någon ättling till BaseException
, och framtida utgåvor i Python 2.x-serien kan börja tillämpa denna begränsning. Därför föreslår jag att du börjar göra alla dina undantagsklasser härledda från Exception
nu. Det har föreslagits att den nakna except:
-formen ska tas bort i Python 3.0, men Guido van Rossum har inte bestämt sig för om detta ska göras eller inte.
Att lyfta strängar som undantag, som i uttalandet raise "Error occurred"
, är föråldrat i Python 2.5 och kommer att utlösa en varning. Målet är att kunna ta bort string-exception-funktionen i några utgåvor.
Se även
- PEP 352 - Obligatorisk superklass för undantag
PEP skriven av Brett Cannon och Guido van Rossum; implementerad av Brett Cannon.
PEP 353: Använda ssize_t som indextyp¶
En omfattande ändring av Pythons C API, där en ny typdefinition Py_ssize_t
används istället för int, gör att tolken kan hantera mer data på 64-bitars plattformar. Denna förändring påverkar inte Pythons kapacitet på 32-bitars plattformar.
Olika delar av Python-tolken använde C:s int-typ för att lagra storlekar eller räkningar; till exempel lagrades antalet objekt i en lista eller tupel i en int. C-kompilatorerna för de flesta 64-bitars plattformar definierar fortfarande int som en 32-bitars typ, så det innebar att listor bara kunde innehålla upp till 2**31 - 1
= 2147483647 objekt. (Det finns faktiskt några olika programmeringsmodeller som 64-bitars C-kompilatorer kan använda - se https://unix.org/version2/whatsnew/lp64_wp.html för en diskussion - men den vanligaste modellen lämnar int som 32 bitar)
En gräns på 2147483647 objekt spelar egentligen ingen roll på en 32-bitars plattform eftersom du får slut på minne innan du når längdgränsen. Varje listobjekt kräver utrymme för en pekare, som är 4 byte, plus utrymme för en PyObject
som representerar objektet. 2147483647*4 är redan fler byte än vad ett 32-bitars adressutrymme kan innehålla.
Det är dock möjligt att adressera så mycket minne på en 64-bitars plattform. Pekarna för en lista av den storleken skulle bara kräva 16 GiB utrymme, så det är inte orimligt att Python-programmerare kan konstruera listor som är så stora. Därför måste Python-tolken ändras så att den använder någon annan typ än int, och detta kommer att vara en 64-bitars typ på 64-bitars plattformar. Ändringen kommer att orsaka inkompatibilitet på 64-bitars maskiner, så det ansågs värt att göra övergången nu, medan antalet 64-bitars användare fortfarande är relativt litet. (Om 5 eller 10 år kanske vi alla använder 64-bitars maskiner, och övergången skulle då vara mer smärtsam)
Denna ändring påverkar främst författare av C-tilläggsmoduler. Python-strängar och containertyper som listor och tupler använder nu Py_ssize_t
för att lagra sin storlek. Funktioner som PyList_Size()
returnerar nu Py_ssize_t
. Kod i tilläggsmoduler kan därför behöva få vissa variabler ändrade till Py_ssize_t
.
Funktionerna PyArg_ParseTuple()
och Py_BuildValue()
har en ny konverteringskod, n
, för Py_ssize_t
. PyArg_ParseTuple()
s#
och t#
ger fortfarande ut int som standard, men du kan definiera makrot PY_SSIZE_T_CLEAN
innan du inkluderar Python.h
för att få dem att returnera Py_ssize_t
.
PEP 353 har ett avsnitt om riktlinjer för konvertering som författare av tillägg bör läsa för att lära sig mer om stöd för 64-bitars plattformar.
Se även
- PEP 353 - Använda ssize_t som indextyp
PEP skrivet och implementerat av Martin von Löwis.
PEP 357: Metoden ”__index__¶
NumPy-utvecklarna hade ett problem som bara kunde lösas genom att lägga till en ny specialmetod, __index__()
. När man använder slice-notation, som i [start:stop:step]
, måste värdena för indexen start, stop och step alla vara antingen heltal eller långa heltal. NumPy definierar en mängd specialiserade heltalstyper som motsvarar osignerade och signerade heltal på 8, 16, 32 och 64 bitar, men det fanns inget sätt att signalera att dessa typer kunde användas som slice-index.
Slicing kan inte bara använda den befintliga metoden __int__()
eftersom den metoden också används för att implementera coercion till heltal. Om slicing använde __int__()
skulle även flyttal bli lagliga slice-index och det är helt klart ett oönskat beteende.
Istället har en ny specialmetod som heter __index__()
lagts till. Den tar inga argument och returnerar ett heltal som anger vilket slice-index som ska användas. Till exempel:
klass C:
def __index__ (self):
return self.value
Returvärdet måste vara antingen ett Python heltal eller ett långt heltal. Tolken kommer att kontrollera att typen som returneras är korrekt, och ger ett TypeError
om detta krav inte uppfylls.
En motsvarande nb_index
slot lades till i C-nivå PyNumberMethods
strukturen för att låta C-tillägg implementera detta protokoll. PyNumber_Index(obj)
kan användas i tilläggskod för att anropa funktionen __index__()
och hämta dess resultat.
Se även
- PEP 357 - Tillåter att vilket objekt som helst används för skivning
PEP skrivet och genomfört av Travis Oliphant.
Andra språkliga förändringar¶
Här är alla ändringar som Python 2.5 gör i kärnan i Python-språket.
Typen
dict
har en ny hook för att låta underklasser tillhandahålla ett standardvärde när en nyckel inte finns i ordboken. När en nyckel inte hittas anropas dictionariets metod__missing__(key)
. Den här hooken används för att implementera den nya klassendefaultdict
i modulencollections
. I följande exempel definieras en ordbok som returnerar noll om någon nyckel saknas:klass zerodict (dikt): def __missing__ (self, key): return 0 d = zerodict({1:1, 2:2}) print d[1], d[2] # Skriver ut 1, 2 print d[3], d[4] # Skriver ut 0, 0
Både 8-bitars och Unicode-strängar har nya
partition(sep)
ochrpartition(sep)
metoder som förenklar ett vanligt användningsfall.Metoden
find(S)
används ofta för att få ett index som sedan används för att skära upp strängen och få de delar som finns före och efter separatorn.partition(sep)
kondenserar det här mönstret till ett enda metodanrop som returnerar en 3-tupel som innehåller delsträngen före separatorn, själva separatorn och delsträngen efter separatorn. Om separatorn inte hittas är det första elementet i tupeln hela strängen och de andra två elementen är tomma.rpartition(sep)
returnerar också en 3-tupel men börjar söka från slutet av strängen;r
står för ”reverse” (omvänd).Några exempel:
>>> ('http://www.python.org').partition('://') ('http', '://', 'www.python.org') >>> ('file:/usr/share/doc/index.html').partition('://') ('file:/usr/share/doc/index.html', '', '') >>> (u'Subject: a quick question').partition(':') (u'Subject', u':', u' a quick question') >>> 'www.python.org'.rpartition('.') ('www.python', '.', 'org') >>> 'www.python.org'.rpartition(':') ('', '', 'www.python.org')
(Implementerat av Fredrik Lundh efter ett förslag av Raymond Hettinger)
Metoderna
startswith()
ochendswith()
för strängtyper accepterar nu tuples av strängar att kontrollera för.def is_image_file (filnamn): return filnamn.endswith(('.gif', '.jpg', '.tiff'))
(Implementerat av Georg Brandl efter ett förslag av Tom Lynn.)
De inbyggda funktionerna
min()
ochmax()
har fått en nyckelordsparameterkey
som är analog med argumentetkey
försort()
. Denna parameter tillhandahåller en funktion som tar ett enda argument och anropas för varje värde i listan;min()
/max()
returnerar elementet med det minsta/största returvärdet från denna funktion. Om du till exempel vill hitta den längsta strängen i en lista kan du göra så här:L = ['medium', 'longest', 'short'] # Skriver ut 'längsta' print max(L, nyckel=len) # Skriver ut 'short', eftersom 'short' lexikografiskt sett har det största värdet print max(L)
(Bidrag från Steven Bethard och Raymond Hettinger.)
Två nya inbyggda funktioner,
any()
ochall()
, utvärderar om en iterator innehåller några sanna eller falska värden.any()
returnerarTrue
om något värde som returneras av iteratorn är sant; annars returnerar denFalse
.all()
returnerarTrue
endast om alla värden som returneras av iteratorn utvärderas som sanna. (Föreslagen av Guido van Rossum, och implementerad av Raymond Hettinger.)Resultatet av en klass
__hash__()
-metod kan nu vara antingen ett långt heltal eller ett vanligt heltal. Om ett långt heltal returneras tas hashvärdet för det värdet. I tidigare versioner krävdes det att hashvärdet var ett vanligt heltal, men i 2.5 ändradesid()
inbyggd så att den alltid returnerar icke-negativa tal, och användare verkar ofta användaid(self)
i__hash__()
-metoder (även om detta avråds).ASCII är nu standardkodning för moduler. Det är nu ett syntaxfel om en modul innehåller stränglitteraler med 8-bitars tecken men inte har en kodningsdeklaration. I Python 2.4 utlöste detta en varning, inte ett syntaxfel. Se PEP 263 för hur man deklarerar en moduls kodning; till exempel kan du lägga till en rad som denna längst upp i källfilen:
# -*- kodning: latin1 -*-
En ny varning,
UnicodeWarning
, utlöses när du försöker jämföra en Unicode-sträng med en 8-bitarssträng som inte kan konverteras till Unicode med standardkodningen ASCII. Resultatet av jämförelsen är false:>>> chr(128) == unichr(128) # Can't convert chr(128) to Unicode __main__:1: UnicodeWarning: Unicode equal comparison failed to convert both arguments to Unicode - interpreting them as being unequal False >>> chr(127) == unichr(127) # chr(127) can be converted True
Tidigare skulle detta ge upphov till ett
UnicodeDecodeError
-undantag, men i 2.5 kunde detta resultera i förbryllande problem vid åtkomst till en ordbok. Om du slog uppunichr(128)
ochchr(128)
användes som nyckel, skulle du få ettUnicodeDecodeError
-undantag. Andra ändringar i 2.5 resulterade i att detta undantag togs upp istället för att undertryckas av koden idictobject.c
som implementerar dictionaries.Att skapa ett undantag för en sådan jämförelse är helt korrekt, men ändringen kan ha brutit kod, så istället infördes
UnicodeWarning
.(Implementerad av Marc-André Lemburg.)
Ett fel som Python-programmerare ibland gör är att glömma att inkludera en
__init__.py
-modul i en paketkatalog. Att felsöka detta misstag kan vara förvirrande och kräver vanligtvis att Python körs med-v
för att logga alla sökvägar. I Python 2.5 utlöses en nyImportWarning
-varning när en import skulle ha hämtat en katalog som ett paket men ingen__init__.py
hittades. Denna varning ignoreras tyst som standard; ange alternativet-Wd
när du kör den körbara Python-filen för att visa varningsmeddelandet. (Implementerad av Thomas Wouters.)Listan över basklasser i en klassdefinition kan nu vara tom. Som ett exempel är detta nu lagligt:
klass C(): pass
(Implementerat av Brett Cannon.)
Förändringar för interaktiv tolk¶
I den interaktiva tolken har quit
och exit
länge varit strängar så att nya användare får ett något hjälpsamt meddelande när de försöker avsluta:
>>> quit
'Use Ctrl-D (i.e. EOF) to exit.'
I Python 2.5 är quit
och exit
nu objekt som fortfarande producerar strängrepresentationer av sig själva, men som också är anropsbara. Nybörjare som försöker quit()
eller exit()
kommer nu att avsluta tolken som de förväntar sig. (Implementerat av Georg Brandl.)
Den körbara Python-filen accepterar nu de långa standardalternativen --help
och --version
; på Windows accepterar den även alternativet /?
för att visa ett hjälpmeddelande. (Implementerat av Georg Brandl.)
Optimeringar¶
Flera av optimeringarna utvecklades vid NeedForSpeed-sprinten, ett evenemang som hölls i Reykjavik, Island, 21-28 maj 2006. Sprinten fokuserade på hastighetsförbättringar av CPython-implementeringen och finansierades av EWT LLC med lokalt stöd från CCP Games. De optimeringar som lades till vid denna sprint är särskilt markerade i följande lista.
När de introducerades i Python 2.4 byggdes de inbyggda typerna
set
ochfrozenset
ovanpå Pythons dictionary-typ. I 2.5 har den interna datastrukturen anpassats för att implementera set, och som ett resultat kommer set att använda en tredjedel mindre minne och är något snabbare. (Implementerat av Raymond Hettinger.)Hastigheten för vissa Unicode-operationer, som att hitta substrängar, strängdelning och kodning och avkodning av teckenkartor, har förbättrats. (Förbättringar av sökning och delning av delsträngar lades till av Fredrik Lundh och Andrew Dalke vid NeedForSpeed-sprintet. Teckenkartor förbättrades av Walter Dörwald och Martin von Löwis)
Funktionen
long(str, base)
är nu snabbare på långa siffersträngar eftersom färre mellanresultat beräknas. Toppen är för strängar med cirka 800–1000 siffror där funktionen är 6 gånger snabbare. (Bidrag från Alan McIntyre och utfört vid NeedForSpeed-sprinten.)Det är nu olagligt att blanda iteration över en fil med
for line in file
och anrop av filobjektetsread()
/readline()
/readlines()
-metoder. Iteration använder en intern buffert och metodernaread*()
använder inte den bufferten. Istället skulle de returnera data som följer efter bufferten, vilket gör att data visas i fel ordning. Att blanda iteration och dessa metoder kommer nu att utlösa ettValueError
från metodenread*()
. (Implementerad av Thomas Wouters.)Modulen
struct
sammanställer nu strängar i strukturformat till en intern representation och cachar denna representation, vilket ger en 20% speedup. (Bidrag från Bob Ippolito vid NeedForSpeed-sprinten.)Modulen
re
fick en 1 eller 2% speedup genom att byta till Pythons allokeringsfunktioner istället för systemetsmalloc()
ochfree()
. (Bidrag från Jack Diederich vid NeedForSpeed-sprinten.)Kodgeneratorns peephole-optimerare utför nu enkel konstantvikning i uttryck. Om du skriver något i stil med
a = 2+3
kommer kodgeneratorn att göra uträkningen och producera kod som motsvarara = 5
. (Föreslagen och implementerad av Raymond Hettinger.)Funktionsanrop är nu snabbare eftersom kodobjekt nu behåller den senast avslutade ramen (en ”zombieram”) i ett internt fält i kodobjektet och återanvänder den nästa gång kodobjektet anropas. (Ursprunglig patch av Michael Hudson, modifierad av Armin Rigo och Richard Jones; utförd vid NeedForSpeed-sprinten.) Frame-objekten är också något mindre, vilket kan förbättra cachelokaliteten och minska minnesanvändningen något. (Bidrag från Neal Norwitz.)
Pythons inbyggda undantag är nu new-style classes, en förändring som snabbar upp instantiering avsevärt. Undantagshanteringen i Python 2.5 är därför ungefär 30% fsnabbare än i 2.4. (Bidrag från Richard Jones, Georg Brandl och Sean Reifschneider vid NeedForSpeed-sprinten.)
Importering cachar nu de sökvägar som prövas och registrerar om de finns eller inte så att tolken gör färre
open()
- ochstat()
-anrop vid start. (Bidrag från Martin von Löwis och Georg Brandl.)
Nya, förbättrade och borttagna moduler¶
Standardbiblioteket fick många förbättringar och buggfixar i Python 2.5. Här är en partiell lista över de mest anmärkningsvärda ändringarna, sorterade alfabetiskt efter modulnamn. Se filen Misc/NEWS
i källträdet för en mer komplett lista över ändringar, eller titta igenom SVN-loggarna för alla detaljer.
Modulen
audioop
har nu stöd för a-LAW-kodning och koden för u-LAW-kodning har förbättrats. (Bidrag från Lars Immisch.)Modulen
codecs
har fått stöd för inkrementella codecs. Funktionencodec.lookup()
returnerar nu enCodecInfo
-instans istället för en tupel.CodecInfo
-instanser beter sig som en 4-tupel för att bevara bakåtkompatibilitet men har också attributenencode
,decode
,incrementalencoder
,incrementaldecoder
,streamwriter
ochstreamreader
. Inkrementella codecs kan ta emot indata och producera utdata i flera delar; utdata är samma som om hela indata hade matats till en icke-inkrementell codec. Se dokumentationen för modulencodecs
för mer information. (Designad och implementerad av Walter Dörwald.)Modulen
collections
har fått en ny typ,defaultdict
, som är en underklass till standardtypendict
. Den nya typen beter sig mestadels som en ordbok men konstruerar ett standardvärde när en nyckel inte finns, och lägger automatiskt till det i ordboken för det begärda nyckelvärdet.Det första argumentet till
defaultdict
:s konstruktör är en fabriksfunktion som anropas när en nyckel begärs men inte hittas. Denna fabriksfunktion tar inte emot några argument, så du kan använda inbyggda typkonstruktörer somlist()
ellerint()
. Du kan t.ex. skapa ett index över ord baserat på deras begynnelsebokstav på följande sätt:words = """Nel mezzo del cammin di nostra vita min ritrovai per una selva oscura som jag inte hade en aning om""".lower().split() index = defaultdict(lista) för w i ord: init_letter = w[0] index[init_letter].append(w)
Utskrift av
index
resulterar i följande utdata:defaultdict(<type 'list'>, {'c': ['cammin', 'che'], 'e': ['era'], 'd': ['del', 'di', 'diritta'], 'm': ['mezzo', 'mi'], 'l': ["la"], "o": ["oscura"], "n": ["nel", "nostra"], 'p': ["per"], "s": ["selva", "smarrita"], 'r': ["ritrovai"], "u": ["una"], "v": ["vita", "via"]}
(Bidrag från Guido van Rossum.)
Den dubbelsidiga kötypen
deque
som tillhandahålls av modulencollections
har nu en metodremove(value)
som tar bort den första förekomsten av värde i kön och ger upphov tillValueError
om värdet inte hittas. (Bidrag från Raymond Hettinger.)Ny modul: Modulen
contextlib
innehåller hjälpfunktioner för användning med den nya ’with
’-satsen. Se avsnitt Modulen contextlib för mer information om denna modul.Ny modul: Modulen
cProfile
är en C-implementering av den befintliga modulenprofile
som har mycket lägre overhead. Modulens gränssnitt är detsamma somprofile
: du körcProfile.run('main()')
för att profilera en funktion, kan spara profildata till en fil, etc. Det är ännu inte känt om Hotshot-profileraren, som också är skriven i C men inte matcharprofile
-modulens gränssnitt, kommer att fortsätta att underhållas i framtida versioner av Python. (Bidrag från Armin Rigo.)Modulen
pstats
för analys av data som uppmätts av profileraren stöder nu också styrning av utdata till valfritt filobjekt genom att tillhandahålla ett stream-argument till konstruktörenStats
. (Bidrag från Skip Montanaro.)Modulen
csv
, som analyserar filer i formatet kommaseparerade värden, har fått flera förbättringar och ett antal buggfixar. Du kan nu ange den maximala storleken i byte för ett fält genom att anropa funktionencsv.field_size_limit(new_limit)
; om du utelämnar argumentet new_limit returneras den aktuella gränsen. Klassenreader
har nu ett attributline_num
som räknar antalet fysiska rader som lästs från källan; poster kan sträcka sig över flera fysiska rader, såline_num
är inte detsamma som antalet lästa poster.CSV-parsern är nu striktare när det gäller citerade fält med flera rader. Tidigare, om en rad slutade inom ett citerat fält utan ett avslutande ny rad-tecken, skulle en ny rad infogas i det returnerade fältet. Detta beteende orsakade problem vid läsning av filer som innehöll vagnreturtecken i fälten, så koden ändrades så att fältet returnerades utan att nya rader infogades. Detta innebär att om det är viktigt med nya rader inbäddade i fält, bör inmatningen delas upp i rader på ett sätt som bevarar de nya raderna.
(Bidrag från Skip Montanaro och Andrew McNamara.)
Klassen
datetime
i modulendatetime
har nu enstrptime(string, format)
-metod för parsning av datumsträngar, bidrag från Josh Spoerri. Den använder samma formattecken somtime.strptime()
ochtime.strftime()
:från datetime import datetime ts = datetime.strptime('10:13:15 2006-03-07', '%H:%M:%S %Y-%m-%d')
Metoden
SequenceMatcher.get_matching_blocks()
i modulendifflib
garanterar nu att den returnerar en minimal lista med block som beskriver matchande undersekvenser. Tidigare kunde algoritmen ibland dela upp ett block med matchande element i två listposter. (Förbättring av Tim Peters.)Modulen
doctest
har fått ettSKIP
-alternativ som hindrar ett exempel från att exekveras överhuvudtaget. Detta är avsett för kodsnuttar som är användningsexempel avsedda för läsaren och som inte egentligen är testfall.En parameter encoding har lagts till i funktionen
testfile()
och klassenDocFileSuite
för att ange filens kodning. Detta gör det enklare att använda icke-ASCII-tecken i tester som ingår i en dokumentsträng. (Bidrag från Bjorn Tillenius.)Paketet
email
har uppdaterats till version 4.0. (Bidrag från Barry Warsaw.)Modulen
fileinput
har gjorts mer flexibel. Unicode-filnamn stöds nu och en mode-parameter med standardvärdet"r"
lades till i funktioneninput()
för att göra det möjligt att öppna filer i binärt eller universal newlines-läge. En annan ny parameter, openhook, låter dig använda en annan funktion änopen()
för att öppna indatafilerna. När du har itererat över filuppsättningen returnerarFileInput
-objektets nyafileno()
filbeskrivaren för den aktuella öppnade filen. (Bidrag från Georg Brandl.)I modulen
gc
returnerar den nya funktionenget_count()
en 3-tupel som innehåller det aktuella antalet insamlingar för de tre GC-generationerna. Detta är redovisningsinformation för skräpsamlaren; när dessa räkningar når ett angivet tröskelvärde kommer en skräpsamling att göras. Den befintliga funktionengc.collect()
tar nu ett valfritt generation-argument på 0, 1 eller 2 för att ange vilken generation som ska samlas in. (Bidrag från Barry Warsaw.)Funktionerna
nsmallest()
ochnlargest()
i modulenheapq
har nu stöd för nyckelordsparameternkey
, liknande den som finns i funktionernamin()
/max()
och metodernasort()
. Till exempel:>>> import heapq >>> L = ["short", 'medium', 'longest', 'longer still'] >>> heapq.nsmallest(2, L) # Return two lowest elements, lexicographically ['longer still', 'longest'] >>> heapq.nsmallest(2, L, key=len) # Return two shortest elements ['short', 'medium']
(Bidrag från Raymond Hettinger.)
Funktionen
itertools.islice()
accepterar nuNone
för start- och stegargumenten. Detta gör den mer kompatibel med attributen för slice-objekt, så att du nu kan skriva följande:s = slice(5) # Skapa ett slice-objekt itertools.islice(iterabel, s.start, s.stop, s.steg)
(Bidrag från Raymond Hettinger.)
Funktionen
format()
i modulenlocale
har ändrats och två nya funktioner har lagts till,format_string()
ochcurrency()
.Funktionen
format()
parameter val kunde tidigare vara en sträng så länge det inte fanns mer än en %char-angivelse; nu måste parametern vara exakt en %char-angivelse utan omgivande text. En valfri monetary-parameter har också lagts till som, om den ärTrue
, kommer att använda lokalens regler för formatering av valuta för att placera en separator mellan grupper om tre siffror.För att formatera strängar med flera %char-angivelser, använd den nya funktionen
format_string()
som fungerar somformat()
men som också stöder blandning av %char-angivelser med godtycklig text.En ny
currency()
-funktion har också lagts till som formaterar ett tal enligt den aktuella lokalens inställningar.(Bidrag från Georg Brandl.)
Modulen
mailbox
genomgick en omfattande omskrivning för att lägga till möjligheten att modifiera brevlådor utöver att läsa dem. En ny uppsättning klasser som inkluderarmbox
,MH
ochMaildir
används för att läsa brevlådor och har en metodadd(message)
för att lägga till meddelanden,remove(key)
för att ta bort meddelanden ochlock()
/unlock()
för att låsa/låsa upp brevlådan. I följande exempel konverteras en brevlåda i maildir-format till en brevlåda i mbox-format:import mailbox # 'factory=None' uses email.Message.Message as the class representing # individual messages. src = mailbox.Maildir('maildir', factory=None) dest = mailbox.mbox('/tmp/mbox') for msg in src: dest.add(msg)
(Bidrag från Gregory K. Johnson. Finansiering tillhandahölls av Googles Summer of Code 2005)
Ny modul: Modulen
msilib
gör det möjligt att skapa Microsoft Installer.msi
-filer och CAB-filer. Visst stöd för att läsa.msi
-databasen ingår också. (Bidrag från Martin von Löwis.)Modulen
nis
stöder nu åtkomst till andra domäner än systemets standarddomän genom att ange ett domän-argument till funktionernanis.match()
ochnis.maps()
. (Bidrag från Ben Bell.)Modulerna
operator
:s funktioneritemgetter()
ochattrgetter()
har nu stöd för flera fält. Ett anrop somoperator.attrgetter('a', 'b')
kommer att returnera en funktion som hämtar attributena
ochb
. Genom att kombinera den här nya funktionen medsort()
-metodenskey
-parameter kan du enkelt sortera listor med flera fält. (Bidrag från Raymond Hettinger.)Modulen
optparse
uppdaterades till version 1.5.1 av Optik-biblioteket. KlassenOptionParser
fick ett attributepilog
, en sträng som skrivs ut efter hjälpmeddelandet, och en metoddestroy()
för att bryta referenscykler som skapas av objektet. (Bidrag från Greg Ward.)Modulen
os
har genomgått flera förändringar. Variabelnstat_float_times
har nu standardvärdet true, vilket innebär attos.stat()
nu kommer att returnera tidsvärden som floats. (Detta betyder inte nödvändigtvis attos.stat()
kommer att returnera tider som är exakta till bråkdelar av en sekund; inte alla system stöder sådan precision)Konstanter med namnen
os.SEEK_SET
,os.SEEK_CUR
ochos.SEEK_END
har lagts till; dessa är parametrarna för funktionenos.lseek()
. Två nya konstanter för låsning äros.O_SHLOCK
ochos.O_EXLOCK
.Två nya funktioner,
wait3()
ochwait4()
, har lagts till. De liknar funktionenwaitpid()
som väntar på att en underordnad process ska avslutas och returnerar en tupel av process-ID och dess avslutningsstatus, menwait3()
ochwait4()
returnerar ytterligare information.wait3()
tar inte emot något process-ID som indata, så den väntar på att en underordnad process ska avslutas och returnerar en 3-tupel av process-id, exit-status, resource-usage som returneras från funktionenresource.getrusage()
.wait4(pid)
tar ett process-ID. (Bidrag från Chad J. Schroeder.)På FreeBSD returnerar funktionen
os.stat()
nu tider med nanosekunders upplösning och det returnerade objektet har nu attributenst_gen
ochst_birthtime
. Attributetst_flags
är också tillgängligt, om plattformen stöder det. (Bidrag från Antti Louko och Diego Pettenò.)Python-felsökaren som tillhandahålls av modulen
pdb
kan nu lagra listor med kommandon som ska utföras när en brytpunkt nås och exekveringen stoppas. När brytpunkt #1 har skapats, angekommandon 1
och ange en serie kommandon som ska köras, avsluta listan medend
. Kommandolistan kan innehålla kommandon som återupptar exekveringen, t.ex.continue
ellernext
. (Bidrag från Grégoire Dooms.)Modulerna
pickle
ochcPickle
accepterar inte längre ett returvärde påNone
från metoden__reduce__()
; metoden måste returnera en tupel av argument istället. Möjligheten att returneraNone
försvann i Python 2.4, så detta avslutar borttagandet av funktionen.Modulen
pkgutil
, som innehåller olika verktygsfunktioner för att hitta paket, har förbättrats för att stödja PEP 302:s import-hooks och fungerar nu även för paket som lagras i ZIP-formatarkiv. (Bidrag från Phillip J. Eby.)Benchmark-sviten pybench av Marc-André Lemburg ingår nu i katalogen
Tools/pybench
. Pybench-sviten är en förbättring jämfört med det vanligt förekommande programmetpystone.py
eftersom pybench ger en mer detaljerad mätning av tolkens hastighet. Den tidsbestämmer särskilda operationer som funktionsanrop, tuple-slicing, metoduppslagningar och numeriska operationer, i stället för att utföra många olika operationer och reducera resultatet till ett enda tal sompystone.py
gör.Modulen
pyexpat
använder nu version 2.0 av Expat-parsern. (Bidrag från Trent Mick.)Klassen
Queue
som tillhandahålls av modulenQueue
har fått två nya metoder.join()
blockerar tills alla objekt i kön har hämtats och all bearbetning av objekten har slutförts. Arbetstrådar anropar den andra nya metoden,task_done()
, för att signalera att bearbetningen av ett objekt har slutförts. (Bidrag från Raymond Hettinger.)De gamla modulerna
regex
ochregsub
, som har varit föråldrade ända sedan Python 2.0, har slutligen tagits bort. Andra borttagna moduler:statcache
,tzparse
,whrandom
.Borttagen: katalogen
lib-old
, som innehåller gamla moduler somdircmp
ochni
, har tagits bort.lib-old
fanns inte med i standardinställningensys.path
, så om inte dina program uttryckligen har lagt till katalogen isys.path
bör borttagningen inte påverka din kod.Modulen
rlcompleter
är inte längre beroende av att modulenreadline
importeras och fungerar därför nu på plattformar som inte är Unix. (Patch från Robert Kiendl.)Klasserna
SimpleXMLRPCServer
ochDocXMLRPCServer
har nu ett attributrpc_paths
som begränsar XML-RPC-operationer till en begränsad uppsättning URL-sökvägar; standard är att endast tillåta'/'
och'/RPC2'
. Omrpc_paths
sätts tillNone
eller en tom tupel inaktiveras denna sökvägskontroll.Modulen
socket
har nu stöd förAF_NETLINK
-sockets på Linux, tack vare en patch från Philippe Biondi. Netlink-sockets är en Linux-specifik mekanism för kommunikation mellan en process i användarrymden och kärnkoden; en inledande artikel om dem finns på https://www.linuxjournal.com/article/7356. I Python-kod representeras netlink-adresser som en tupel av 2 heltal,(pid, group_mask)
.Två nya metoder för socket-objekt,
recv_into(buffer)
ochrecvfrom_into(buffer)
, lagrar de mottagna data i ett objekt som stöder buffertprotokollet istället för att returnera data som en sträng. Detta innebär att du kan lägga in data direkt i en array eller en minnesmappad fil.Socket-objekt har också accessormetoderna
getfamily()
,gettype()
ochgetproto()
för att hämta värden för familj, typ och protokoll för sockeln.Ny modul: Modulen
spwd
innehåller funktioner för att komma åt databasen med skugglösenord på system som stöder skugglösenord.Modulen
struct
är nu snabbare eftersom den kompilerar formatsträngar tillStruct
-objekt med metodernapack()
ochunpack()
. Detta liknar hur modulenre
låter dig skapa kompilerade objekt för reguljära uttryck. Du kan fortfarande använda modulnivåfunktionernapack()
ochunpack()
; de skaparStruct
-objekt och cachar dem. Eller så kan du användaStruct
-instanser direkt:s = struct.Struct('ih3s') data = s.pack(1972, 187, 'abc') år, nummer, namn = s.unpack(data)
Du kan också packa och packa upp data till och från buffertobjekt direkt med hjälp av metoderna
pack_into(buffert, offset, v1, v2, ...)
ochunpack_from(buffert, offset)
. På så sätt kan du lagra data direkt i en array eller en minnesmappad fil.(
Struct
-objekt implementerades av Bob Ippolito vid NeedForSpeed-sprinten. Stöd för buffertobjekt lades till av Martin Blais, också vid NeedForSpeed-sprintet)Python-utvecklarna bytte från CVS till Subversion under utvecklingsprocessen för 2.5. Information om den exakta byggversionen finns tillgänglig som variabeln
sys.subversion
, en 3-tupel av(tolknamn, grennamn, revisionsintervall)
. Till exempel rapporterade min kopia av 2.5 vid tidpunkten för skrivandet('CPython', 'trunk', '45313:45315')
.Den här informationen är också tillgänglig för C-tillägg via funktionen
Py_GetBuildInfo()
som returnerar en sträng med bygginformation som den här:"trunk:45355:45356M, Apr 13 2006, 07:42:19"
. (Bidrag från Barry Warsaw.)En annan ny funktion,
sys._current_frames()
, returnerar de aktuella stackramarna för alla trådar som körs som en ordbok som mappar trådidentifierare till den översta stackram som är aktiv i tråden när funktionen anropas. (Bidrag från Tim Peters.)Klassen
TarFile
i modulentarfile
har nu en metodextractall()
som extraherar alla medlemmar från arkivet till den aktuella arbetskatalogen. Det är också möjligt att ange en annan katalog som extraktionsmål och att endast packa upp en delmängd av arkivets medlemmar.Komprimeringen som används för en tarfil som öppnas i stream-läge kan nu autodetekteras med hjälp av läget
'r|*'
. (Bidrag från Lars Gustäbel.)Med modulen
threading
kan du nu ställa in den stackstorlek som används när nya trådar skapas. Funktionenstack_size([*size*])
returnerar den aktuella konfigurerade stackstorleken och genom att ange den valfria parametern size anges ett nytt värde. Det är inte alla plattformar som stöder ändring av stackstorleken, men Windows, POSIX threading och OS/2 gör det. (Bidrag från Andrew MacIntyre.)Modulen
unicodedata
har uppdaterats för att använda version 4.1.0 av Unicodes teckendatabas. Version 3.2.0 krävs av vissa specifikationer, så den är fortfarande tillgänglig somunicodedata.ucd_3_2_0
.Ny modul: Modulen
uuid
genererar universellt unika identifierare (UUID) enligt RFC 4122. RFC definierar flera olika UUID-versioner som genereras från en startsträng, från systemegenskaper eller helt slumpmässigt. Denna modul innehåller enUUID
-klass och funktioner med namnenuuid1()
,uuid3()
,uuid4()
ochuuid5()
för att generera olika versioner av UUID. (Version 2 av UUID anges inte i RFC 4122 och stöds inte av den här modulen)>>> import uuid >>> # make a UUID based on the host ID and current time >>> uuid.uuid1() UUID('a8098c1a-f86e-11da-bd1a-00112444be1e') >>> # make a UUID using an MD5 hash of a namespace UUID and a name >>> uuid.uuid3(uuid.NAMESPACE_DNS, 'python.org') UUID('6fa459ea-ee8a-3ca4-894e-db77e160355e') >>> # make a random UUID >>> uuid.uuid4() UUID('16fd2706-8baf-433b-82eb-8c7fada847da') >>> # make a UUID using a SHA-1 hash of a namespace UUID and a name >>> uuid.uuid5(uuid.NAMESPACE_DNS, 'python.org') UUID('886313e1-3b8a-5372-9b90-0c9aee199e5d')
(Bidrag från Ka-Ping Yee.)
Modulens
weakref
-typerWeakKeyDictionary
ochWeakValueDictionary
fick nya metoder för att iterera över de svaga referenser som finns i ordboken. Metodernaiterkeyrefs()
ochkeyrefs()
lades till iWeakKeyDictionary
, ochitervaluerefs()
ochvaluerefs()
lades till iWeakValueDictionary
. (Bidrag från Fred L. Drake, Jr.)Modulen
webbrowser
har fått ett antal förbättringar. Den kan nu användas som ett skript medpython -m webbrowser
, med en URL som argument; det finns ett antal omkopplare för att styra beteendet (-n
för ett nytt webbläsarfönster,-t
för en ny flik). Nya funktioner på modulnivå,open_new()
ochopen_new_tab()
, har lagts till för att stödja detta. Modulens funktionopen()
har stöd för ytterligare en funktion, en autoraise-parameter som signalerar om det öppna fönstret ska höjas när det är möjligt. Ett antal ytterligare webbläsare lades till i listan över webbläsare som stöds, t.ex. Firefox, Opera, Konqueror och elinks. (Bidrag från Oleg Broytmann och Georg Brandl.)Modulen
xmlrpclib
stöder nu returnering avdatetime
-objekt för XML-RPC:s datatyp. Tillföruse_datetime=True
tillloads()
-funktionen ellerUnmarshaller
-klassen för att aktivera den här funktionen. (Bidrag från Skip Montanaro.)Modulen
zipfile
stöder nu ZIP64-versionen av formatet, vilket innebär att ett .zip-arkiv nu kan vara större än 4 GiB och kan innehålla enskilda filer som är större än 4 GiB. (Bidrag från Ronald Oussoren.)zlib
-modulensCompress
- ochDecompress
-objekt stöder nu encopy()
-metod som gör en kopia av objektets interna tillstånd och returnerar ett nyttCompress
- ellerDecompress
-objekt. (Bidrag från Chris AtLee.)
Paketet ctypes¶
Paketet ctypes
, skrivet av Thomas Heller, har lagts till i standardbiblioteket. Med ctypes
kan du anropa godtyckliga funktioner i delade bibliotek eller DLL:er. Långvariga användare kanske minns modulen dl
, som innehåller funktioner för att ladda delade bibliotek och anropa funktioner i dem. Paketet ctypes
är mycket mer avancerat.
För att ladda ett delat bibliotek eller en DLL måste du skapa en instans av klassen CDLL
och ange namnet på eller sökvägen till det delade biblioteket eller DLL:en. När det är gjort kan du anropa godtyckliga funktioner genom att komma åt dem som attribut till CDLL
-objektet.
import ctypes
libc = ctypes.CDLL('libc.so.6')
result = libc.printf("Line of output\n")
Typkonstruktörer för de olika C-typerna tillhandahålls: c_int()
, c_float()
, c_double()
, c_char_p()
(motsvarande char*), och så vidare. Till skillnad från Pythons typer är C-versionerna alla mutabla; du kan tilldela deras value
-attribut för att ändra det omslutna värdet. Pythons heltal och strängar kommer automatiskt att konverteras till motsvarande C-typer, men för andra typer måste du anropa rätt typkonstruktör. (Och jag menar måste; om du gör fel resulterar det ofta i att tolken kraschar med ett segmenteringsfel)
Du bör inte använda c_char_p()
med en Python-sträng när C-funktionen kommer att ändra minnesområdet, eftersom Python-strängar ska vara oföränderliga; att bryta mot denna regel kommer att orsaka förbryllande buggar. När du behöver en modifierbar minnesarea, använd create_string_buffer()
:
s = "detta är en sträng"
buf = ctypes.skapa_sträng_buffer(s)
libc.strfry(buf)
C-funktioner antas returnera heltal, men du kan ställa in attributet restype
för funktionsobjektet för att ändra detta:
>>> libc.atof('2.71828')
-1783957616
>>> libc.atof.restype = ctypes.c_double
>>> libc.atof('2.71828')
2.71828
ctypes
tillhandahåller också en omslagslösning för Pythons C API i form av objektet ctypes.pythonapi
. Det här objektet släpper inte det globala tolklåset innan en funktion anropas, eftersom låset måste hållas kvar när tolkens kod anropas. Det finns en konstruktör av typen py_object
som skapar en pekare av typen PyObject*. En enkel användning:
import ctypes
d = {}
ctypes.pythonapi.PyObject_SetItem(ctypes.py_object(d),
ctypes.py_object("abc"), ctypes.py_object(1))
# d is now {'abc', 1}.
Glöm inte att använda py_object()
; om det utelämnas får du ett segmenteringsfel.
ctypes
har funnits ett tag, men folk skriver och distribuerar fortfarande handkodade tilläggsmoduler eftersom man inte kan lita på att ctypes
finns. Kanske kommer utvecklare att börja skriva Pythonomslag ovanpå ett bibliotek som nås via ctypes
istället för tilläggsmoduler, nu när ctypes
ingår i Pythons kärna.
Se även
- https://web.archive.org/web/20180410025338/http://starship.python.net/crew/theller/ctypes/
Webbsidan pre-stdlib ctypes, med en handledning, referens och FAQ.
Dokumentationen för modulen ctypes
.
ElementTree-paketet¶
En delmängd av Fredrik Lundhs ElementTree-bibliotek för bearbetning av XML har lagts till i standardbiblioteket som xml.etree
. De tillgängliga modulerna är ElementTree
, ElementPath
och ElementInclude
från ElementTree 1.2.6. Acceleratormodulen cElementTree
ingår också.
I resten av detta avsnitt ges en kort översikt över hur du använder ElementTree. Fullständig dokumentation för ElementTree finns på https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm.
ElementTree representerar ett XML-dokument som ett träd med elementnoder. Dokumentets textinnehåll lagras som attributen text
och tail
i (Detta är en av de största skillnaderna mellan ElementTree och Document Object Model; i DOM finns det många olika typer av noder, inklusive TextNode
)
Den vanligaste parsingfunktionen är parse()
, som tar antingen en sträng (som antas innehålla ett filnamn) eller ett filliknande objekt och returnerar en ElementTree
-instans:
from xml.etree import ElementTree as ET
träd = ET.parse('ex-1.xml')
feed = urllib.urlopen(
'http://planet.python.org/rss10.xml')
träd = ET.parse(feed)
När du har en ElementTree
-instans kan du anropa dess getroot()
-metod för att hämta rotnoden Element
.
Det finns också en XML()
-funktion som tar en sträng och returnerar en Element
-nod (inte en ElementTree
). Denna funktion ger ett snyggt sätt att införliva XML-fragment och närmar sig bekvämligheten med en XML-litteral:
svg = ET.XML("""<svg width="10px" version="1.0">
</svg>""")
svg.set('höjd', '320px')
svg.append(elem1)
Varje XML-element stöder vissa ordboksliknande och vissa listliknande åtkomstmetoder. Ordboksliknande åtgärder används för att komma åt attributvärden och listliknande åtgärder används för att komma åt underordnade noder.
Operation |
Resultat |
---|---|
|
Returnerar det n:te underordnade elementet. |
|
Returnerar listan med m’th till n’th underordnade element. |
|
Returnerar antalet underordnade element. |
|
Returnerar en lista med underordnade element. |
|
Lägger till elem2 som ett barn. |
|
Infogar elem2 på den angivna platsen. |
|
Raderar det n:te underordnade elementet. |
|
Returnerar en lista med attributnamn. |
|
Returnerar värdet för attributet name. |
|
Ställer in ett nytt värde för attributet name. |
|
Hämtar ordlistan som innehåller attribut. |
|
Raderar attributet namn. |
Kommentarer och bearbetningsinstruktioner representeras också som Element
-noder. För att kontrollera om en nod är en kommentar eller en bearbetningsinstruktion:
om elem.tag är ET.Comment:
...
elif elem.tag är ET.ProcessingInstruction:
...
För att generera XML-utdata bör du anropa metoden ElementTree.write()
. Precis som parse()
kan den ta antingen en sträng eller ett filliknande objekt:
# Kodning är US-ASCII
tree.write('output.xml')
# Kodningen är UTF-8
f = open('output.xml', 'w')
tree.write(f, kodning='utf-8')
(Observera att standardkodningen för utdata är ASCII. För allmänt XML-arbete, där ett elements namn kan innehålla godtyckliga Unicode-tecken, är ASCII inte en särskilt användbar kodning eftersom den kommer att ge upphov till ett undantag om ett elements namn innehåller tecken med värden som är större än 127. Därför är det bäst att ange en annan kodning, t.ex. UTF-8, som kan hantera alla Unicode-tecken)
Detta avsnitt är endast en partiell beskrivning av ElementTree-gränssnitten. Läs paketets officiella dokumentation för mer information.
Se även
- https://web.archive.org/web/20201124024954/http://effbot.org/zone/element-index.htm
Officiell dokumentation för ElementTree.
Paketet hashlib¶
En ny hashlib
-modul, skriven av Gregory P. Smith, har lagts till för att ersätta md5
- och sha
-modulerna. hashlib
lägger till stöd för ytterligare säkra hashar (SHA-224, SHA-256, SHA-384 och SHA-512). När modulen är tillgänglig använder den OpenSSL för snabba plattformsoptimerade implementeringar av algoritmer.
De gamla modulerna md5
och sha
finns fortfarande kvar som omslag runt hashlib för att bevara bakåtkompatibilitet. Den nya modulens gränssnitt ligger mycket nära de gamla modulernas, men är inte identiskt. Den mest betydande skillnaden är att konstruktörsfunktionerna för att skapa nya hashingobjekt har olika namn.
# Gamla versioner
h = md5.md5()
h = md5.new()
# Ny version
h = hashlib.md5()
# Gamla versioner
h = sha.sha()
h = sha.new()
# Ny version
h = hashlib.sha1()
# Hash som inte var tillgängliga tidigare
h = hashlib.sha224()
h = hashlib.sha256()
h = hashlib.sha384()
h = hashlib.sha512()
# Alternativ form
h = hashlib.new('md5') # Ange algoritmen som en sträng
När ett hash-objekt har skapats är dess metoder desamma som tidigare: update(string)
hashar den angivna strängen till det aktuella digest-läget, digest()
och hexdigest()
returnerar digest-värdet som en binär sträng eller en sträng med hex-siffror, och copy()
returnerar ett nytt hash-objekt med samma digest-läge.
Se även
Dokumentationen för modulen hashlib
.
Paketet sqlite3¶
Modulen pysqlite (https://www.pysqlite.org), ett omslag för den inbäddade databasen SQLite, har lagts till i standardbiblioteket under paketnamnet sqlite3
.
SQLite är ett C-bibliotek som tillhandahåller en lättviktig diskbaserad databas som inte kräver en separat serverprocess och som gör det möjligt att komma åt databasen med en icke-standardvariant av frågespråket SQL. Vissa applikationer kan använda SQLite för intern datalagring. Det är också möjligt att prototypa en applikation med SQLite och sedan porta koden till en större databas som PostgreSQL eller Oracle.
pysqlite skrevs av Gerhard Häring och tillhandahåller ett SQL-gränssnitt som överensstämmer med DB-API 2.0-specifikationen som beskrivs av PEP 249.
Om du kompilerar Python-källan själv bör du notera att källträdet inte innehåller SQLite-koden, utan endast omslagsmodulen. Du måste ha SQLite-biblioteken och headers installerade innan du kompilerar Python, och byggprocessen kommer att kompilera modulen när de nödvändiga headers är tillgängliga.
För att använda modulen måste du först skapa ett Connection
-objekt som representerar databasen. Här kommer data att lagras i /tmp/example
-filen:
conn = sqlite3.connect('/tmp/example')
Du kan också ange det speciella namnet :memory:
för att skapa en databas i RAM.
När du har en Connection
kan du skapa ett Cursor
-objekt och anropa dess execute()
-metod för att utföra SQL-kommandon:
c = conn.cursor()
# Skapa tabell
c.execute('''skapa tabell aktier
(datum text, trans text, symbol text,
qty real, price real)''')
# Infoga en rad med data
c.execute("""infoga i aktier
values ('2006-01-05','BUY','RHAT',100,35.14)""")
Vanligtvis kommer dina SQL-operationer att behöva använda värden från Python-variabler. Du bör inte sätta ihop din fråga med hjälp av Pythons strängoperationer eftersom det är osäkert; det gör ditt program sårbart för en SQL-injektionsattack.
Använd istället DB-API:s parametersubstitution. Sätt ?
som en platshållare där du vill använda ett värde och tillhandahåll sedan en tupel av värden som det andra argumentet till markörens execute()
-metod. (Andra databasmoduler kan använda en annan platshållare, t.ex. %s
eller :1
) Till exempel:
# Gör aldrig detta -- osäkert!
symbol = 'IBM'
c.execute("... där symbol = '%s'" % symbol)
# Gör så här istället
t = (symbol,)
c.execute('select * from stocks where symbol=?', t)
# Större exempel
for t in (('2006-03-28', 'BUY', 'IBM', 1000, 45.00),
('2006-04-05', 'BUY', 'MSOFT', 1000, 72.00),
('2006-04-06', 'SÄLJ', 'IBM', 500, 53,00),
):
c.execute('insert into stocks values (?,?,?,?,?,?)', t)
Om du vill hämta data efter att ha kört en SELECT-sats kan du antingen behandla markören som en iterator, anropa markörens metod fetchone()
för att hämta en enda matchande rad eller anropa fetchall()
för att hämta en lista över matchande rader.
I detta exempel används iteratorn form:
>>> c = conn.cursor()
>>> c.execute('select * from stocks order by price')
>>> for row in c:
... print row
...
(u'2006-01-05', u'BUY', u'RHAT', 100, 35.140000000000001)
(u'2006-03-28', u'BUY', u'IBM', 1000, 45.0)
(u'2006-04-06', u'SELL', u'IBM', 500, 53.0)
(u'2006-04-05', u'BUY', u'MSOFT', 1000, 72.0)
>>>
För mer information om SQL-dialekten som stöds av SQLite, se https://www.sqlite.org.
Se även
- https://www.pysqlite.org
Webbsidan för pysqlite.
- https://www.sqlite.org
SQLite-webbsidan; dokumentationen beskriver syntaxen och de tillgängliga datatyperna för den SQL-dialekt som stöds.
Dokumentationen för modulen sqlite3
.
- PEP 249 - API-specifikation för databaser 2.0
PEP skriven av Marc-André Lemburg.
Paketet wsgiref¶
Web Server Gateway Interface (WSGI) v1.0 definierar ett standardgränssnitt mellan webbservrar och Python webbapplikationer och beskrivs i PEP 333. Paketet wsgiref
är en referensimplementering av WSGI-specifikationen.
Paketet innehåller en grundläggande HTTP-server som kör en WSGI-applikation; den här servern är användbar för felsökning men är inte avsedd för produktionsanvändning. Att konfigurera en server tar bara några rader kod:
from wsgiref import simple_server
wsgi_app = ...
host = ''
port = 8000
httpd = simple_server.make_server(host, port, wsgi_app)
httpd.serve_forever()
Se även
- https://web.archive.org/web/20160331090247/http://wsgi.readthedocs.org/en/latest/
En central webbplats för WSGI-relaterade resurser.
- PEP 333 - Python Web Server Gateway-gränssnitt v1.0
PEP skriven av Phillip J. Eby.
Ändringar i Build och C API¶
Ändringar i Pythons byggprocess och i C API inkluderar:
Pythons källträd konverterades från CVS till Subversion, i en komplex migreringsprocedur som övervakades och genomfördes felfritt av Martin von Löwis. Proceduren utvecklades som PEP 347.
Coverity, ett företag som marknadsför ett verktyg för källkodsanalys kallat Prevent, har redovisat resultatet av sin undersökning av Pythons källkod. Analysen visade att det fanns ett 60-tal buggar som snabbt åtgärdades. Många av buggarna var problem med återräkning och uppstod ofta i felhanteringskod. Se https://scan.coverity.com för statistik.
Den största ändringen i C API:et kom från PEP 353, som ändrar tolken så att den använder en
Py_ssize_t
-typdefinition istället för int. Se det tidigare avsnittet PEP 353: Använda ssize_t som indextyp för en diskussion om denna ändring.Bytekodkompilatorns design har ändrats en hel del. Den genererar inte längre bytekod genom att genomkorsa parseträdet. Istället konverteras parseträdet till ett abstrakt syntaxträd (eller AST), och det är det abstrakta syntaxträdet som genomkorsas för att producera bytekoden.
Det är möjligt för Python-kod att få AST-objekt genom att använda den inbyggda
compile()
och ange_ast.PyCF_ONLY_AST
som värdet på parametern flags:from _ast import PyCF_ONLY_AST ast = kompilera("""a=0 för i i intervall(10): a += i """, "<string>", 'exec', PyCF_ONLY_AST) uppdrag = ast.body[0] for_loop = ast.body[1]
Ingen officiell dokumentation har ännu skrivits för AST-koden, men PEP 339 diskuterar designen. Om du vill börja lära dig mer om koden kan du läsa definitionen av de olika AST-noderna i
Parser/Python.asdl
. Ett Python-skript läser denna fil och genererar en uppsättning C-strukturdefinitioner iInclude/Python-ast.h
.PyParser_ASTFromString()
ochPyParser_ASTFromFile()
, definierade iInclude/pythonrun.h
, tar Python-källan som indata och returnerar roten till en AST som representerar innehållet. Denna AST kan sedan omvandlas till ett kodobjekt medPyAST_Compile()
. För mer information, läs källkoden och ställ sedan frågor på python-dev.AST-koden utvecklades under Jeremy Hyltons ledning och implementerades av (i alfabetisk ordning) Brett Cannon, Nick Coghlan, Grant Edwards, John Ehresman, Kurt Kaiser, Neal Norwitz, Tim Peters, Armin Rigo och Neil Schemenauer, plus deltagarna i ett antal AST-sprintar vid konferenser som PyCon.
Evan Jones patch till obmalloc, som först beskrevs i ett föredrag på PyCon DC 2005, tillämpades. Python 2.4 allokerade små objekt i 256K stora arenor, men frigjorde aldrig arenor. Med denna patch kommer Python att frigöra arenor när de är tomma. Nettoeffekten är att på vissa plattformar, när du allokerar många objekt, kan Pythons minnesanvändning faktiskt minska när du tar bort dem och minnet kan returneras till operativsystemet. (Implementerad av Evan Jones och omarbetad av Tim Peters)
Observera att denna ändring innebär att tilläggsmoduler måste vara mer försiktiga när de allokerar minne. Pythons API har många olika funktioner för att allokera minne som är grupperade i familjer. Till exempel är
PyMem_Malloc()
,PyMem_Realloc()
ochPyMem_Free()
en familj som allokerar råminne, medanPyObject_Malloc()
,PyObject_Realloc()
ochPyObject_Free()
är en annan familj som ska användas för att skapa Python-objekt.Tidigare reducerades alla dessa olika familjer till plattformens funktioner
malloc()
ochfree()
. Detta innebar att det inte spelade någon roll om du gjorde fel och allokerade minne med funktionenPyMem
men frigjorde det med funktionenPyObject
. Med 2.5:s ändringar av obmalloc gör dessa familjer nu olika saker och felmatchningar kommer förmodligen att resultera i ett segfault. Du bör noggrant testa dina C-tilläggsmoduler med Python 2.5.De inbyggda set-typerna har nu ett officiellt C API. Anropa
PySet_New()
ochPyFrozenSet_New()
för att skapa en ny uppsättning,PySet_Add()
ochPySet_Discard()
för att lägga till och ta bort element, ochPySet_Contains()
ochPySet_Size()
för att undersöka uppsättningens tillstånd. (Bidrag från Raymond Hettinger.)C-kod kan nu få information om den exakta revisionen av Python-tolken genom att anropa funktionen
Py_GetBuildInfo()
som returnerar en sträng med bygginformation som denna:"trunk:45355:45356M, Apr 13 2006, 07:42:19"
. (Bidrag från Barry Warsaw.)Två nya makron kan användas för att ange C-funktioner som är lokala för den aktuella filen så att en snabbare anropskonvention kan användas.
Py_LOCAL(type)
deklarerar att funktionen returnerar ett värde av den angivna typen och använder en snabbuppringningskvalifierare.Py_LOCAL_INLINE(type)
gör samma sak och begär också att funktionen ska vara inlined. Om makroPY_LOCAL_AGGRESSIVE
definieras innanpython.h
inkluderas, aktiveras en uppsättning mer aggressiva optimeringar för modulen; du bör jämföra resultaten för att ta reda på om dessa optimeringar faktiskt gör koden snabbare. (Bidrag från Fredrik Lundh vid NeedForSpeed-sprinten.)PyErr_NewException(name, base, dict)
kan nu acceptera en tupel av basklasser som sitt base-argument. (Bidrag från Georg Brandl.)Funktionen
PyErr_Warn()
för att utfärda varningar är nu föråldrad till förmån förPyErr_WarnEx(category, message, stacklevel)
som låter dig ange antalet stapelramar som skiljer denna funktion och den som anropar. En stacklevel på 1 är den funktion som anroparPyErr_WarnEx()
, 2 är funktionen ovanför den, och så vidare. (Tillagt av Neal Norwitz.)CPython-tolken är fortfarande skriven i C, men koden kan nu kompileras med en C++-kompilator utan fel. (Implementerad av Anthony Baxter, Martin von Löwis, Skip Montanaro.)
Funktionen
PyRange_New()
togs bort. Den var aldrig dokumenterad, användes aldrig i kärnkoden och hade farligt slapp felkontroll. I det osannolika fallet att dina tillägg använde den, kan du ersätta den med något som följande:range = PyObject_CallFunction((PyObject*) &PyRange_Type, "lll", start, stopp, steg);
Hamnspecifika ändringar¶
MacOS X (10.3 och senare): dynamisk laddning av moduler använder nu funktionen
dlopen()
istället för MacOS-specifika funktioner.MacOS X: ett
--enable-universalsdk
-omkopplingsalternativ lades till i configure-skriptet som kompilerar tolken som en universell binär fil som kan köras på både PowerPC- och Intel-processorer. (Bidrag från Ronald Oussoren; bpo-2573.)Windows:
.dll
stöds inte längre som filnamnstillägg för tilläggsmoduler..pyd
är nu det enda filnamnstillägget som kommer att sökas efter.
Portning till Python 2.5¶
I detta avsnitt listas tidigare beskrivna ändringar som kan kräva ändringar i din kod:
ASCII är nu standardkodning för moduler. Det är nu ett syntaxfel om en modul innehåller stränglitteraler med 8-bitars tecken men inte har en kodningsdeklaration. I Python 2.4 utlöste detta en varning, inte ett syntaxfel.
Tidigare var attributet
gi_frame
för en generator alltid ett frame-objekt. På grund av ändringarna i PEP 342 som beskrivs i avsnitt PEP 342: Nya generatorfunktioner, är det nu möjligt förgi_frame
att varaNone
.En ny varning,
UnicodeWarning
, utlöses när du försöker jämföra en Unicode-sträng med en 8-bitarssträng som inte kan konverteras till Unicode med standardkodningen ASCII. Tidigare ledde sådana jämförelser till ettUnicodeDecodeError
-undantag.Bibliotek: Modulen
csv
är nu strängare när det gäller citerade fält med flera rader. Om dina filer innehåller nya rader inbäddade i fält, bör inmatningen delas upp i rader på ett sätt som bevarar de nya raderna.Bibliotek:
locale
-modulensformat()
-funktioner accepterade tidigare vilken sträng som helst så länge det inte fanns mer än en %char-angivelse. I Python 2.5 måste argumentet vara exakt en %char-angivelse utan omgivande text.Bibliotek: Modulerna
pickle
ochcPickle
accepterar inte längre ett returvärde påNone
från metoden__reduce__()
; metoden måste returnera en tupel av argument istället. Modulerna accepterar inte heller längre den föråldrade nyckelordsparametern bin.Bibliotek: Klasserna
SimpleXMLRPCServer
ochDocXMLRPCServer
har nu attributetrpc_paths
som begränsar XML-RPC-operationer till en begränsad uppsättning URL-sökvägar; standard är att endast tillåta'/'
och'/RPC2'
. Omrpc_paths
sätts tillNone
eller en tom tupel inaktiveras denna sökvägskontroll.C API: Många funktioner använder nu
Py_ssize_t
istället för int för att möjliggöra bearbetning av mer data på 64-bitars maskiner. Tilläggskod kan behöva göra samma ändring för att undvika varningar och för att stödja 64-bitars maskiner. Se det tidigare avsnittet PEP 353: Använda ssize_t som indextyp för en diskussion om den här ändringen.C API: Ändringarna i obmalloc innebär att du måste vara försiktig så att du inte blandar användningen av funktionsfamiljerna
PyMem_*
ochPyObject_*
. Minne som allokerats med en familjs*_Malloc
måste frigöras med motsvarande familjs*_Free
-funktion.
Tack till¶
Författaren vill tacka följande personer för förslag, korrigeringar och hjälp med olika utkast av denna artikel: Georg Brandl, Nick Coghlan, Phillip J. Eby, Lars Gustäbel, Raymond Hettinger, Ralf W. Grosse-Kunstleve, Kent Johnson, Iain Lowe, Martin von Löwis, Fredrik Lundh, Andrew McNamara, Skip Montanaro, Gustavo Niemeyer, Paul Prescod, James Pryor, Mike Rovner, Scott Weikart, Barry Warsaw, Thomas Wouters.