Vad är nytt i Python 2.0¶
- Författare:
A.M. Kuchling och Moshe Zadka
Introduktion¶
En ny version av Python, version 2.0, släpptes den 16 oktober 2000. Den här artikeln beskriver de spännande nyheterna i 2.0, lyfter fram några andra användbara ändringar och pekar på några inkompatibla ändringar som kan kräva att koden skrivs om.
Pythons utveckling stannar aldrig helt upp mellan utgåvorna, och ett stadigt flöde av buggfixar och förbättringar skickas alltid in. En mängd mindre korrigeringar, några optimeringar, ytterligare dokumentationer och bättre felmeddelanden gick in i 2.0; att lista dem alla skulle vara omöjligt, men de är verkligen betydelsefulla. Konsultera de offentligt tillgängliga CVS-loggarna om du vill se hela listan. Dessa framsteg beror på att de fem utvecklare som arbetar för PythonLabs nu får betalt för att spendera sina dagar med att fixa buggar, och även på grund av den förbättrade kommunikationen som följer av att flytta till SourceForge.
Vad sägs om Python 1.6?¶
Python 1.6 kan ses som Python-versionen för kontraktsförpliktelser. Efter att kärnutvecklingsgruppen lämnade CNRI i maj 2000 begärde CNRI att en 1.6-version skulle skapas, som skulle innehålla allt arbete med Python som hade utförts på CNRI. Python 1.6 representerar därför tillståndet i CVS-trädet i maj 2000, med den mest betydande nya funktionen Unicode-stöd. Utvecklingen fortsatte naturligtvis efter maj, så 1.6-trädet fick några korrigeringar för att säkerställa att det är framåtkompatibelt med Python 2.0. 1.6 är därför en del av Pythons utveckling, och inte en sidogren.
Så, borde du intressera dig för Python 1.6? Förmodligen inte. Versionerna 1.6final och 2.0beta1 släpptes samma dag (5 september 2000) och planen är att Python 2.0 ska vara färdig inom en månad eller så. Om du har applikationer att underhålla verkar det inte finnas någon mening med att bryta saker genom att flytta till 1.6, fixa dem och sedan ha en ny omgång av brott inom en månad genom att flytta till 2.0; det är bättre att bara gå direkt till 2.0. De flesta av de riktigt intressanta funktionerna som beskrivs i det här dokumentet finns bara i 2.0, eftersom mycket arbete gjordes mellan maj och september.
Ny utvecklingsprocess¶
Den viktigaste förändringen i Python 2.0 är kanske inte alls i koden, utan i hur Python utvecklas: i maj 2000 började Python-utvecklarna använda de verktyg som SourceForge tillhandahåller för att lagra källkod, spåra felrapporter och hantera kön av patchar som skickas in. För att rapportera buggar eller skicka in patchar för Python 2.0, använd verktygen för buggspårning och patchhantering som finns tillgängliga på Pythons projektsida, som finns på https://sourceforge.net/projects/python/.
Den viktigaste av de tjänster som nu finns hos SourceForge är Pythons CVS-träd, det versionsstyrda arkiv som innehåller källkoden för Python. Tidigare fanns det ungefär 7 personer som hade skrivrättigheter till CVS-trädet, och alla patchar måste inspekteras och checkas in av någon av personerna på denna korta lista. Det här var naturligtvis inte särskilt skalbart. Genom att flytta CVS-trädet till SourceForge blev det möjligt att ge fler personer skrivbehörighet; i september 2000 kunde 27 personer checka in ändringar, vilket är en fyrfaldig ökning. Detta möjliggör storskaliga förändringar som inte skulle ha genomförts om de hade behövt filtreras genom den lilla gruppen av kärnutvecklare. En dag fick till exempel Peter Schneider-Kamp för sig att släppa K&R C-kompatibiliteten och konvertera C-källan för Python till ANSI C. Efter att ha fått godkännande på e-postlistan python-dev satte han igång med en mängd incheckningar som varade i ungefär en vecka, andra utvecklare anslöt sig för att hjälpa till och jobbet var gjort. Om det bara hade funnits fem personer med skrivbehörighet hade den uppgiften förmodligen betraktats som ”trevlig, men inte värd den tid och ansträngning som krävs” och den hade aldrig blivit utförd.
Övergången till att använda SourceForges tjänster har resulterat i en anmärkningsvärd ökning av utvecklingshastigheten. Patchar skickas nu in, kommenteras, revideras av andra personer än den som ursprungligen skickade in dem och skickas fram och tillbaka mellan olika personer tills patchen anses vara värd att checka in. Buggar spåras på en central plats och kan tilldelas en specifik person för åtgärdande, och vi kan räkna antalet öppna buggar för att mäta framstegen. Detta har inte skett utan kostnad: utvecklarna har nu mer e-post att hantera, fler e-postlistor att följa och särskilda verktyg måste skrivas för den nya miljön. SourceForge skickar till exempel standardmeddelanden om patch- och buggaviseringar som är helt oanvändbara, så Ka-Ping Yee skrev en HTML-skärmskrapa som skickar mer användbara meddelanden.
Det enkla sättet att lägga till kod orsakade en del initiala växtvärk, till exempel att kod checkades in innan den var klar eller utan att få ett tydligt godkännande från utvecklargruppen. Den godkännandeprocess som har utvecklats liknar till viss del den som används av Apache-gruppen. Utvecklare kan rösta +1, +0, -0 eller -1 på en patch. +1 och -1 innebär att man godkänner eller förkastar en patch, medan +0 och -0 innebär att utvecklaren i stort sett är likgiltig inför förändringen, men med en liten positiv eller negativ lutning. Den viktigaste förändringen jämfört med Apache-modellen är att omröstningen i huvudsak är rådgivande, vilket gör att Guido van Rossum, som har status som Benevolent Dictator For Life, vet vad den allmänna uppfattningen är. Han kan fortfarande ignorera resultatet av en omröstning och godkänna eller förkasta en ändring även om gemenskapen inte håller med honom.
Att producera en faktisk patch är det sista steget i att lägga till en ny funktion, och är vanligtvis lätt jämfört med den tidigare uppgiften att komma på en bra design. Diskussioner om nya funktioner kan ofta explodera i långa trådar på e-postlistor, vilket gör diskussionen svår att följa, och ingen kan läsa alla inlägg till python-dev. Därför har en relativt formell process inrättats för att skriva Python Enhancement Proposals (PEPs), med RFC-processen på internet som förebild. PEPs är utkast till dokument som beskriver en föreslagen ny funktion, och revideras kontinuerligt tills gemenskapen når ett samförstånd, antingen accepterar eller förkastar förslaget. Citat från introduktionen till PEP 1, ”PEP Purpose and Guidelines”:
PEP står för Python Enhancement Proposal (förslag till förbättring av Python). Ett PEP är ett designdokument som ger information till Python-gemenskapen eller beskriver en ny funktion för Python. PEP ska innehålla en kortfattad teknisk specifikation av funktionen och en motivering för funktionen.
Vi avser att PEP:er ska vara de primära mekanismerna för att föreslå nya funktioner, för att samla in synpunkter på en fråga och för att dokumentera de designbeslut som har tagits i Python. PEP-författaren är ansvarig för att bygga konsensus inom gemenskapen och dokumentera avvikande åsikter.
Läs resten av PEP 1 för detaljer om PEP:s redaktionella process, stil och format. PEPs finns i Python CVS-trädet på SourceForge, även om de inte är en del av Python 2.0-distributionen, och finns också tillgängliga i HTML-format från https://peps.python.org/. I september 2000 fanns det 25 PEP:er, från PEP 201, ”Lockstep Iteration”, till PEP 225, ”Elementwise/Objectwise Operators”.
Unicode¶
Den största nyheten i Python 2.0 är en ny grundläggande datatyp: Unicode-strängar. Unicode använder 16-bitarsnummer för att representera tecken i stället för 8-bitarsnummer som används av ASCII, vilket innebär att 65 536 olika tecken kan stödjas.
Det slutliga gränssnittet för Unicode-stöd togs fram genom otaliga, ofta stormiga diskussioner på e-postlistan python-dev, och implementerades till största delen av Marc-André Lemburg, baserat på en Unicode-strängtypsimplementering av Fredrik Lundh. En detaljerad förklaring av gränssnittet skrevs upp som PEP 100, ”Python Unicode Integration”. Den här artikeln kommer helt enkelt att täcka de viktigaste punkterna om Unicode-gränssnitten.
I Pythons källkod skrivs Unicode-strängar som u"string"
. Godtyckliga Unicode-tecken kan skrivas med hjälp av en ny escape-sekvens, \uHHHH
, där HHHH är ett fyrsiffrigt hexadecimalt tal från 0000 till FFFF. Den befintliga escape-sekvensen xHH
kan också användas, och oktala escapes kan användas för tecken upp till U+01FF, som representeras av \777
.
Unicode-strängar är, precis som vanliga strängar, en oföränderlig sekvenstyp. De kan indexeras och skivas, men inte modifieras på plats. Unicode-strängar har en encode( [encoding] )
-metod som returnerar en 8-bitars sträng i önskad kodning. Kodningar namnges av strängar, till exempel 'ascii'
, 'utf-8'
, 'iso-8859-1'
, eller vad som helst. Ett codec-API är definierat för att implementera och registrera nya kodningar som sedan är tillgängliga i ett Python-program. Om en kodning inte specificeras är standardkodningen vanligtvis 7-bitars ASCII, men den kan ändras för din Python-installation genom att anropa funktionen sys.setdefaultencoding(encoding)
i en anpassad version av site.py
.
Kombination av 8-bitars och Unicode-strängar tvingar alltid till Unicode, med hjälp av standard ASCII-kodning; resultatet av 'a' + u'bc'
är u'abc'
.
Nya inbyggda funktioner har lagts till och befintliga inbyggda funktioner har modifierats för att stödja Unicode:
unichr(ch)
returnerar en Unicode-sträng som är 1 tecken lång och innehåller tecknet ch.ord(u)
, där u är en reguljär sträng eller Unicode-sträng med 1 tecken, returnerar numret på tecknet som ett heltal.unicode(string [, encoding] [, errors] )
skapar en Unicode-sträng från en 8-bitarssträng.encoding
är en sträng som anger vilken kodning som skall användas. Parameternerrors
anger hur tecken som är ogiltiga för den aktuella kodningen ska behandlas; om värdet'strict'
anges kommer ett undantag att uppstå vid alla kodningsfel, medan'ignore'
gör att felen ignoreras i tysthet och'replace'
använder U+FFFD, det officiella ersättningstecknet, vid eventuella problem.Satsen
exec
och olika inbyggda funktioner someval()
,getattr()
ochsetattr()
kommer också att acceptera Unicode-strängar såväl som vanliga strängar. (Det är möjligt att processen med att fixa detta missade några inbyggda funktioner; om du hittar en inbyggd funktion som accepterar strängar men inte accepterar Unicode-strängar alls, rapportera det som en bugg)
En ny modul, unicodedata
, ger ett gränssnitt till Unicodes teckenegenskaper. Till exempel returnerar unicodedata.category(u'A')
den 2-teckens strängen ’Lu’, där ’L’ anger att det är en bokstav och ’u’ betyder att det är versaler. unicodedata.bidirectional(u'\u0660')
returnerar ’AN’, vilket betyder att U+0660 är ett arabiskt tal.
Modulen codecs
innehåller funktioner för att slå upp befintliga kodningar och registrera nya. Om du inte vill implementera en ny kodning kommer du oftast att använda funktionen codecs.lookup(encoding)
, som returnerar en tupel med 4 element: (encode_func, decode_func, stream_reader, stream_writer)
.
encode_func är en funktion som tar en Unicode-sträng och returnerar en 2-tupel
(sträng, längd)
. string är en 8-bitars sträng som innehåller en del (kanske hela) av Unicode-strängen som konverterats till den givna kodningen, och length berättar hur stor del av Unicode-strängen som konverterades.decode_func är motsatsen till encode_func, tar en 8-bitarssträng och returnerar en 2-tupel
(ustring, length)
, bestående av den resulterande Unicode-strängen ustring och heltalet length som anger hur mycket av 8-bitarssträngen som förbrukades.stream_reader är en klass som stöder avkodning av indata från en ström. stream_reader(file_obj) returnerar ett objekt som stöder metoderna
read()
,readline()
ochreadlines()
. Dessa metoder kommer alla att översätta från den givna kodningen och returnera Unicode-strängar.stream_writer är på samma sätt en klass som stöder kodning av utdata till en ström. stream_writer(file_obj) returnerar ett objekt som stöder metoderna
write()
ochwritelines()
. Dessa metoder förväntar sig Unicode-strängar och översätter dem till den angivna kodningen vid utmatning.
Följande kod skriver till exempel en Unicode-sträng till en fil och kodar den som UTF-8:
import codecs
unistr = u'\u0660\u2000ab ...'
(UTF8_encode, UTF8_decode,
UTF8_streamreader, UTF8_streamwriter) = codecs.lookup('UTF-8')
output = UTF8_streamwriter( open( '/tmp/output', 'wb') )
output.write( unistr )
output.close()
Följande kod skulle då läsa UTF-8-data från filen:
input = UTF8_streamreader( open( '/tmp/output', 'rb') )
print repr(input.read())
input.close()
Unicode-medvetna reguljära uttryck är tillgängliga via modulen re
, som har en ny underliggande implementation kallad SRE skriven av Fredrik Lundh på Secret Labs AB.
Ett kommandoradsalternativ -U
har lagts till som gör att Python-kompilatorn tolkar alla stränglitteraler som Unicode-stränglitteraler. Detta är avsett att användas för att testa och framtidssäkra din Python-kod, eftersom någon framtida version av Python kan släppa stödet för 8-bitars strängar och endast tillhandahålla Unicode-strängar.
Listförståelse¶
Listor är en viktig datatyp i Python och många program manipulerar en lista vid något tillfälle. Två vanliga operationer på listor är att loopa över dem och antingen välja ut de element som uppfyller ett visst kriterium eller tillämpa någon funktion på varje element. Om du till exempel har en lista med strängar kanske du vill plocka ut alla strängar som innehåller en viss delsträng, eller ta bort efterföljande blanksteg från varje rad.
De befintliga funktionerna map()
och filter()
kan användas för detta ändamål, men de kräver en funktion som ett av sina argument. Detta är bra om det finns en befintlig inbyggd funktion som kan skickas direkt, men om det inte finns det måste du skapa en liten funktion för att göra det arbete som krävs, och Pythons scoping-regler gör resultatet fult om den lilla funktionen behöver ytterligare information. Ta det första exemplet i föregående stycke, att hitta alla strängar i listan som innehåller en given delsträng. Du skulle kunna skriva följande för att göra det:
# Given the list L, make a list of all strings
# containing the substring S.
sublist = filter( lambda s, substring=S:
string.find(s, substring) != -1,
L)
På grund av Pythons scoping-regler används ett standardargument så att den anonyma funktion som skapas av lambda
-uttrycket vet vilken delsträng som söks. Listförståelse gör detta renare:
sublist = [ s for s in L if string.find(s, S) != -1 ]
Listkomprehensioner har formen:
[ uttryck för expr i sekvens1
för expr2 i sekvens2 ...
för exprN i sekvensN
om villkor ]
Klausulerna for
…in
innehåller de sekvenser som skall itereras över. Sekvenserna behöver inte vara lika långa, eftersom de inte itereras parallellt, utan från vänster till höger; detta förklaras tydligare i följande stycken. Elementen i den genererade listan kommer att vara de successiva värdena av uttryck. Den avslutande if
-satsen är valfri; om den finns med utvärderas uttryck och läggs till i resultatet endast om villkor är sant.
För att göra semantiken mycket tydlig är en listförståelse likvärdig med följande Python-kod:
för expr1 i sekvens1:
för expr2 i sekvens2:
...
för exprN i sekvensN:
if (villkor):
# Lägg till värdet av
# uttrycket till den
# resulterande listan.
Detta innebär att när det finns flera for
…in
-klausuler, kommer den resulterande listan att vara lika med produkten av längden på alla sekvenser. Om du har två listor med längden 3, är utdatalistan 9 element lång:
seq1 = 'abc'
seq2 = (1,2,3)
>>> [ (x,y) for x in seq1 for y in seq2]
[('a', 1), ('a', 2), ('a', 3), ('b', 1), ('b', 2), ('b', 3), ('c', 1),
('c', 2), ('c', 3)]
För att undvika att införa en tvetydighet i Pythons grammatik, om uttryck skapar en tupel, måste den omges av parenteser. Den första listförståelsen nedan är ett syntaxfel, medan den andra är korrekt:
# Syntaxfel
[ x,y för x i seq1 för y i seq2]
# Korrekt
[ (x,y) för x i seq1 för y i seq2]
Idén med listcomprehensions kommer ursprungligen från det funktionella programmeringsspråket Haskell (https://www.haskell.org). Greg Ewing argumenterade mycket effektivt för att lägga till dem i Python och skrev den första patchen för listförståelse, som sedan diskuterades under en till synes oändlig tid på e-postlistan python-dev och hölls uppdaterad av Skip Montanaro.
Förstärkt uppdrag¶
Augmented assignment operators, en annan länge efterfrågad funktion, har lagts till i Python 2.0. Förstärkta tilldelningsoperatorer inkluderar +=
, -=
, *=
, och så vidare. Till exempel, uttalandet a += 2
ökar värdet på variabeln a
med 2, vilket motsvarar den något längre a = a + 2
.
Den fullständiga listan över tilldelningsoperatorer som stöds är +=
, -=
, *=
, /=
, %=
, **=
, &=
, |=
, ^=
, >>=
och <<=
. Python-klasser kan åsidosätta de utökade tilldelningsoperatorerna genom att definiera metoder med namnet __iadd__()
, __isub__()
, etc. Till exempel lagrar följande Number
-klass ett tal och stöder användning av += för att skapa en ny instans med ett ökat värde.
klass Nummer:
def __init__(self, värde):
self.value = värde
def __iadd__(self, inkrement):
return Number( self.value + ökning)
n = Antal(5)
n += 3
print n.värde
Specialmetoden __iadd__()
anropas med värdet av inkrementet och ska returnera en ny instans med ett lämpligt modifierat värde; detta returvärde binds som det nya värdet av variabeln på vänster sida.
Augmented assignment-operatorer introducerades först i programmeringsspråket C, och de flesta C-avledda språk, till exempel awk, C++, Java, Perl och PHP stöder dem också. Augmented assignment-patchen implementerades av Thomas Wouters.
Strängmetoder¶
Hittills har strängmanipuleringsfunktionaliteten legat i modulen string
, som vanligtvis var en frontend för modulen strop
skriven i C. Tillägget av Unicode innebar en svårighet för modulen strop
, eftersom alla funktioner måste skrivas om för att acceptera antingen 8-bitars eller Unicode-strängar. För funktioner som string.replace()
, som tar 3 strängargument, innebär det åtta möjliga permutationer och därmed komplicerad kod.
Istället flyttar Python 2.0 problemet till strängtypen, vilket gör strängmanipuleringsfunktionalitet tillgänglig via metoder på både 8-bitars strängar och Unicode-strängar:
>>> 'andrew'.capitalize()
'Andrew'
>>> 'hostname'.replace('os', 'linux')
'hlinuxtname'
>>> 'moshe'.find('sh')
2
En sak som inte har förändrats, trots ett anmärkningsvärt aprilskämt, är att Python-strängar är oföränderliga. Strängmetoderna returnerar alltså nya strängar och ändrar inte den sträng som de arbetar med.
Den gamla string
-modulen finns fortfarande kvar för bakåtkompatibilitet, men den fungerar mest som en frontend till de nya string-metoderna.
Två metoder som inte har någon parallell i pre-2.0-versioner, även om de fanns i JPython under ganska lång tid, är startswith()
och endswith()
. s.startswith(t)
är likvärdigt med s[:len(t)] == t
, medan s.endswith(t)
är likvärdigt med s[-len(t):] == t
.
En annan metod som förtjänar ett särskilt omnämnande är join()
. Metoden join()
för en sträng tar emot en parameter, en sekvens av strängar, och är likvärdig med funktionen string.join()
från den gamla modulen string
, med omvända argument. Med andra ord, s.join(seq)
är likvärdig med den gamla string.join(seq, s)
.
Sophämtning av cykler¶
C-implementeringen av Python använder referensräkning för att implementera skräpinsamling. Varje Python-objekt håller reda på antalet referenser som pekar på det självt och justerar antalet när referenser skapas eller förstörs. När referensantalet når noll är objektet inte längre tillgängligt, eftersom du måste ha en referens till ett objekt för att komma åt det, och om antalet är noll finns det inte längre några referenser.
Referensräkning har några trevliga egenskaper: det är lätt att förstå och implementera, och den resulterande implementationen är portabel, ganska snabb och reagerar bra med andra bibliotek som implementerar sina egna minneshanteringsscheman. Det stora problemet med referensräkning är att det ibland inte inser att objekt inte längre är tillgängliga, vilket resulterar i en minnesläcka. Detta händer när det finns cykler av referenser.
Tänk på den enklaste möjliga cykeln, en klassinstans som har en referens till sig själv:
instance = NågonKlass()
instance.myself = instans
Efter att ovanstående två rader kod har exekverats är referensantalet för instance
2; en referens är från variabeln med namnet 'instance
och den andra är från myself
-attributet för instansen.
Om nästa kodrad är del instance
, vad händer då? Referensantalet för instance
minskas med 1, så att det har ett referensantal på 1; referensen i attributet myself
existerar fortfarande. Instansen är dock inte längre tillgänglig via Python-kod och kan raderas. Flera objekt kan delta i en cykel om de har referenser till varandra, vilket leder till att alla objekt läcker.
Python 2.0 löser detta problem genom att periodiskt köra en algoritm för cykeldetektering som letar efter otillgängliga cykler och raderar de inblandade objekten. En ny gc
-modul innehåller funktioner för att utföra en skräpsamling, få felsökningsstatistik och ställa in samlarens parametrar.
Att köra cykeldetekteringsalgoritmen tar lite tid och kommer därför att resultera i lite extra overhead. Förhoppningen är att Python 2.1, efter att vi har fått erfarenhet av cykelinsamlingen från att använda 2.0, ska kunna minimera overhead med noggrann inställning. Det är ännu inte uppenbart hur mycket prestanda som går förlorad, eftersom benchmarking av detta är knepigt och beror avgörande på hur ofta programmet skapar och förstör objekt. Detekteringen av cykler kan inaktiveras när Python kompileras, om du inte har råd med ens en liten hastighetsnedsättning eller misstänker att cykelinsamlingen är buggig, genom att ange --without-cycle-gc
switch när du kör configure scriptet.
Flera personer tog sig an detta problem och bidrog till en lösning. En tidig implementering av metoden för cykeldetektering skrevs av Toby Kelsey. Den nuvarande algoritmen föreslogs av Eric Tiedemann under ett besök på CNRI, och Guido van Rossum och Neil Schemenauer skrev två olika implementeringar, som senare integrerades av Neil. Många andra personer kom med förslag under resans gång; arkiven från mars 2000 på e-postlistan python-dev innehåller de flesta relevanta diskussionerna, särskilt i trådarna med titlarna ”Reference cycle collection for Python” och ”Finalization again”.
Övriga förändringar i kärnverksamheten¶
Olika mindre ändringar har gjorts i Pythons syntax och inbyggda funktioner. Ingen av ändringarna är särskilt långtgående, men de är praktiska bekvämligheter.
Mindre språkliga ändringar¶
En ny syntax gör det mer praktiskt att anropa en given funktion med en tupel av argument och/eller en ordbok med nyckelordsargument. I Python 1.5 och tidigare skulle du använda den inbyggda funktionen apply()
: apply(f, args, kw)
anropar funktionen f()
med argumenttupeln args och nyckelordsargumenten i ordlistan kw. apply()
är densamma i 2.0, men tack vare en patch från Greg Ewing är f(*args, **kw)
ett kortare och tydligare sätt att uppnå samma effekt. Denna syntax är symmetrisk med syntaxen för att definiera funktioner:
def f(*args, **kw):
# args är en tupel av positionella args,
# kw är en ordbok med nyckelordsargument
...
print
-satsen kan nu få sin utdata riktad till ett filliknande objekt genom att följa print
med >> file
, liknande omdirigeringsoperatorn i Unix-skal. Tidigare var man tvungen att antingen använda write()
-metoden för det filliknande objektet, vilket inte är lika bekvämt och enkelt som print
, eller så kunde man tilldela ett nytt värde till sys.stdout
och sedan återställa det gamla värdet. För att skicka utdata till standardfel är det mycket enklare att skriva detta:
print >> sys.stderr, "Warning: action field not supplied"
Moduler kan nu döpas om när de importeras, med syntaxen import module as name
eller from module import name as othername
. Korrigeringen skickades in av Thomas Wouters.
En ny formateringsstil är tillgänglig när operatorn %
används; ’%r’ infogar argumentets repr()
. Detta lades också till av symmetriskäl, den här gången för symmetri med den befintliga formatstilen ’%s’, som infogar str()
för sitt argument. Till exempel returnerar '%r %s' % ('abc', 'abc')
en sträng som innehåller 'abc' abc
.
Tidigare fanns det inget sätt att implementera en klass som åsidosatte Pythons inbyggda in
-operator och implementerade en anpassad version. obj in seq
returnerar sant om obj finns i sekvensen seq; Python beräknar detta genom att helt enkelt prova varje index i sekvensen tills antingen obj hittas eller ett IndexError
påträffas. Moshe Zadka bidrog med en patch som lägger till en __contains__()
magisk metod för att tillhandahålla en anpassad implementation för in
. Dessutom kan nya inbyggda objekt skrivna i C definiera vad in
betyder för dem via en ny slot i sekvensprotokollet.
I tidigare versioner av Python användes en rekursiv algoritm för att radera objekt. Djupt nästlade datastrukturer kunde leda till att tolken fyllde upp C-stacken och kraschade; Christian Tismer skrev om raderingslogiken för att åtgärda detta problem. Jeremy Hylton skrev om koden så att den inte längre kraschade, utan istället gav ett användbart resultat. Till exempel efter den här koden:
a = []
b = []
a.append(a)
b.append(b)
Jämförelsen a==b
returnerar sant, eftersom de två rekursiva datastrukturerna är isomorfa. Se tråden ”trashcan and PR#7” i april 2000-arkiven på e-postlistan python-dev för diskussionen som ledde fram till den här implementationen och några användbara relevanta länkar. Observera att jämförelser nu också kan ge upphov till undantag. I tidigare versioner av Python skulle en jämförelseoperation som cmp(a,b)
alltid ge ett svar, även om en användardefinierad __cmp__()
-metod stötte på ett fel, eftersom det resulterande undantaget helt enkelt skulle sväljas i tysthet.
Arbete har gjorts för att portera Python till 64-bitars Windows på Itanium-processorn, mestadels av Trent Mick från ActiveState. (Förvirrande nog är sys.platform
fortfarande 'win32
på Win64 eftersom det verkar som om MS Visual C++ för att underlätta portning behandlar kod som 32-bitars på Itanium) PythonWin stöder också Windows CE; se Python CE-sidan på https://pythonce.sourceforge.net/ för mer information.
En annan ny plattform är Darwin/MacOS X; initialt stöd för den finns i Python 2.0. Dynamisk laddning fungerar om du anger ”configure –with-dyld –with-suffix=.x”. Mer information finns i README i Pythons källdistribution.
Ett försök har gjorts för att lindra ett av Pythons problem, det ofta förvirrande NameError
-undantaget när kod refererar till en lokal variabel innan variabeln har tilldelats ett värde. Följande kod ger till exempel upphov till ett undantag vid print
-satsen i både 1.5.2 och 2.0; i 1.5.2 ges ett NameError
-undantag, medan 2.0 ger upphov till ett nytt UnboundLocalError
-undantag. UnboundLocalError
är en underklass till NameError
, så all befintlig kod som förväntar sig att NameError
ska ges upphov till bör fortfarande fungera:
def f():
print "i=",i
i = i + 1
f()
Två nya undantag, TabError
och IndentationError
, har introducerats. De är båda underklasser till SyntaxError
och uppstår när Python-kod är felaktigt indragen.
Ändringar av inbyggda funktioner¶
En ny inbyggd funktion, zip(seq1, seq2, ...)
, har lagts till. zip()
returnerar en lista med tupler där varje tupel innehåller det i:te elementet från var och en av argumentsekvenserna. Skillnaden mellan zip()
och map(None, seq1, seq2)
är att map()
fyller sekvenserna med None
om sekvenserna inte alla är lika långa, medan zip()
trunkerar den returnerade listan till längden på den kortaste argumentsekvensen.
Funktionerna int()
och long()
accepterar nu en valfri ”base”-parameter när det första argumentet är en sträng. int('123', 10)
returnerar 123, medan int('123', 16)
returnerar 291. int(123, 16)
ger upphov till ett TypeError
-undantag med meddelandet ”can’t convert non-string with explicit base”.
En ny variabel som innehåller mer detaljerad versionsinformation har lagts till i modulen sys
. sys.version_info
är en tupel (major, minor, micro, level, serial)
Till exempel, i en hypotetisk 2.0.1beta1, skulle sys.version_info
vara (2, 0, 1, 'beta', 1)
. level är en sträng som "alpha"
, "beta"
eller "final"
för en slutlig version.
Dictionaries har en udda ny metod, setdefault(key, default)
, som beter sig på samma sätt som den befintliga metoden get()
. Men om nyckeln saknas, returnerar setdefault()
både värdet på default som get()
skulle göra, och infogar det också i ordboken som värdet för key. Således följande rader med kod:
if dict.has_key( nyckel ): return dict[nyckel]
annat:
dict[key] = []
returnera dict[nyckel]
kan reduceras till en enda return dict.setdefault(key, [])
-sats.
Tolken ställer in ett maximalt rekursionsdjup för att fånga upp okontrollerad rekursion innan C-stacken fylls och orsakar en kärndump eller GPF. Tidigare fastställdes denna gräns när du kompilerade Python, men i 2.0 kan det maximala rekursionsdjupet läsas och ändras med hjälp av sys.getrecursionlimit()
och sys.setrecursionlimit()
. Standardvärdet är 1000, och ett ungefärligt maximalt värde för en viss plattform kan hittas genom att köra ett nytt skript, Misc/find_recursionlimit.py
.
Portning till 2.0¶
Nya Python-utgåvor försöker hårt att vara kompatibla med tidigare utgåvor, och resultatet har varit ganska bra. Vissa ändringar anses dock vara tillräckligt användbara, vanligtvis för att de åtgärdar ursprungliga designbeslut som visade sig vara aktivt felaktiga, för att bryta bakåtkompatibilitet inte alltid kan undvikas. I detta avsnitt listas de ändringar i Python 2.0 som kan orsaka att gammal Python-kod bryts.
Den förändring som förmodligen kommer att bryta mest kod är att strama upp de argument som accepteras av vissa metoder. Vissa metoder skulle ta flera argument och behandla dem som en tupel, särskilt olika listmetoder som append()
och insert()
. I tidigare versioner av Python, om L
är en lista, lägger L.append( 1,2 )
till tupeln (1,2)
till listan. I Python 2.0 orsakar detta ett TypeError
-undantag, med meddelandet: ”append kräver exakt 1 argument; 2 ges”. Lösningen är att helt enkelt lägga till en extra uppsättning parenteser för att skicka båda värdena som en tupel: L.append( (1,2) )
.
De tidigare versionerna av dessa metoder var mer förlåtande eftersom de använde en gammal funktion i Pythons C-gränssnitt för att analysera sina argument; 2.0 moderniserar dem till att använda PyArg_ParseTuple()
, den aktuella argumentanalysfunktionen, som ger mer användbara felmeddelanden och behandlar anrop med flera argument som fel. Om du absolut måste använda 2.0 men inte kan fixa din kod kan du redigera Objects/listobject.c
och definiera preprocessorsymbolen NO_STRICT_LIST_APPEND
för att bevara det gamla beteendet; detta rekommenderas dock inte.
Vissa av funktionerna i modulen socket
är fortfarande förlåtande på det här sättet. Till exempel är socket.connect( ('hostname', 25) )
den korrekta formen, som skickar en tupel som representerar en IP-adress, men socket.connect('hostname', 25)
fungerar också. socket.connect_ex
och socket.bind
är på samma sätt lättsamma. 2.0alpha1 skärpte dessa funktioner, men eftersom dokumentationen faktiskt använde den felaktiga formen med flera argument skrev många människor kod som skulle brytas med den strängare kontrollen. GvR backade ur förändringarna inför allmänhetens reaktion, så för socket
-modulen fixades dokumentationen och formen med flera argument är helt enkelt markerad som föråldrad; den kommer att skärpas igen i en framtida Python-version.
Escapen x
i stränglitteraler tar nu exakt 2 hexsiffror. Tidigare användes alla hexadecimaler efter ”x” och de lägsta 8 bitarna av resultatet, så att ”x123456” motsvarade ”x56”.
Undantagen AttributeError
och NameError
har fått ett mer vänligt felmeddelande, vars text kommer att vara något i stil med 'Spam'-instansen har inget attribut 'ägg'
eller namnet 'ägg' är inte definierat
. Tidigare var felmeddelandet bara det saknade attributnamnet ägg
, och kod skriven för att dra nytta av detta faktum kommer att brytas i 2.0.
En del arbete har gjorts för att göra heltal och långa heltal lite mer utbytbara. I 1.5.2 lades stöd för stora filer till för Solaris, för att göra det möjligt att läsa filer större än 2 GiB; detta gjorde att tell()
-metoden för filobjekt returnerade ett långt heltal istället för ett vanligt heltal. Viss kod subtraherade två filoffset och försökte använda resultatet för att multiplicera en sekvens eller skära en sträng, men detta gav upphov till ett TypeError
. I 2.0 kan långa heltal användas för att multiplicera eller skära en sekvens, och det kommer att bete sig som du intuitivt förväntar dig; 3L * 'abc'
ger ’abcabcabc’, och (0,1,2,3)[2L:4L]
ger (2,3). Långa heltal kan också användas i olika sammanhang där tidigare endast heltal accepterades, t.ex. i metoden seek()
för filobjekt och i de format som stöds av operatorn %
(%d
, %i
, %x
etc.). Till exempel kommer "%d" % 2L**64
att ge strängen 18446744073709551616
.
Den mest subtila förändringen för långa heltal är att str()
av ett långt heltal inte längre har ett efterföljande ”L”-tecken, även om repr()
fortfarande innehåller det. ’L’ irriterade många som ville skriva ut långa heltal som såg ut precis som vanliga heltal, eftersom de var tvungna att anstränga sig för att klippa bort tecknet. Detta är inte längre ett problem i 2.0, men kod som gör str(longval)[:-1]
och antar att ’L’ finns där, kommer nu att förlora den sista siffran.
Att ta repr()
av en float använder nu en annan formateringsprecision än str()
. repr()
använder %.17g
formatsträng för C:s sprintf()
, medan str()
använder %.12g
som tidigare. Effekten är att repr()
ibland kan visa fler decimaler än str()
, för vissa tal. Till exempel kan talet 8,1 inte representeras exakt binärt, så repr(8.1)
är '8.0999999999999996'
, medan str(8,1) är '8.1'
.
Kommandoradsalternativet -X
, som förvandlade alla standardundantag till strängar istället för klasser, har tagits bort; standardundantagen kommer nu alltid att vara klasser. Modulen exceptions
som innehåller standardundantagen har översatts från Python till en inbyggd C-modul, skriven av Barry Warsaw och Fredrik Lundh.
Förändringar av utbyggnad och inbäddning¶
Vissa av ändringarna är dolda och kommer bara att vara uppenbara för personer som skriver C-tilläggsmoduler eller bäddar in en Python-tolk i en större applikation. Om du inte har att göra med Pythons C API kan du hoppa över det här avsnittet.
Versionsnumret för Python C API ökades, så C-tillägg som kompilerats för 1.5.2 måste kompileras om för att fungera med 2.0. På Windows är det inte möjligt för Python 2.0 att importera ett tredjepartstillägg som är byggt för Python 1.5.x på grund av hur Windows DLL:er fungerar, så Python kommer att ge upphov till ett undantag och importen misslyckas.
Användare av Jim Fultons ExtensionClass-modul kommer att bli glada över att få reda på att hooks har lagts till så att ExtensionClasses nu stöds av isinstance()
och issubclass()
. Detta innebär att du inte längre behöver komma ihåg att skriva kod som if type(obj) == myExtensionClass
, utan kan använda den mer naturliga if isinstance(obj, myExtensionClass)
.
Filen Python/importdl.c
, som var en massa #ifdefs för att stödja dynamisk laddning på många olika plattformar, rensades upp och omorganiserades av Greg Stein. importdl.c
är nu ganska liten, och plattformsspecifik kod har flyttats till ett gäng Python/dynload_*.c
-filer. En annan uppstädning: det fanns också ett antal my*.h
-filer i Include/-katalogen som innehöll olika portabilitetshacks; de har slagits samman till en enda fil, Include/pyport.h
.
Vladimir Marangozovs efterlängtade malloc-omstrukturering slutfördes, för att göra det enkelt att få Python-tolken att använda en anpassad allokering istället för C:s standard malloc()
. För dokumentation, läs kommentarerna i Include/pymem.h
och Include/objimpl.h
. För de långa diskussioner under vilka gränssnittet hamrades fram, se webbarkiven för listorna ’patches’ och ’python-dev’ på python.org.
Nya versioner av utvecklingsmiljön GUSI för MacOS har stöd för POSIX-trådar. Därför fungerar nu Pythons stöd för POSIX-trådar på Macintosh. Stöd för trådar som använder GNU pth
-biblioteket i användarutrymmet har också bidragit.
Stödet för trådar i Windows har också förbättrats. Windows stöder trådlås som använder kärnobjekt endast i händelse av konkurrens; i det vanliga fallet när det inte finns någon konkurrens använder de enklare funktioner som är en storleksordning snabbare. En trådad version av Python 1.5.2 på NT är dubbelt så långsam som en otrådad version; med ändringarna i 2.0 är skillnaden bara 10%. Yakov Markovitch har bidragit med dessa förbättringar.
Python 2.0:s källkod använder nu bara ANSI C-prototyper, så för att kompilera Python krävs nu en ANSI C-kompilator och det går inte längre att använda en kompilator som bara stöder K&R C.
Tidigare använde den virtuella Python-maskinen 16-bitars tal i sin bytekod, vilket begränsade storleken på källfiler. I synnerhet påverkade detta den maximala storleken på bokstavslistor och lexikon i Python-källkod; ibland kunde personer som genererade Python-kod stöta på denna gräns. En patch av Charles G. Waldman höjer gränsen från 2**16
till 2**32
.
Tre nya bekvämlighetsfunktioner avsedda för att lägga till konstanter till en moduls ordbok vid modulens initialiseringstid har lagts till: PyModule_AddObject()
, PyModule_AddIntConstant()
och PyModule_AddStringConstant()
. Var och en av dessa funktioner tar ett modulobjekt, en nollavslutad C-sträng som innehåller det namn som ska läggas till och ett tredje argument för det värde som ska tilldelas namnet. Det tredje argumentet är ett Python-objekt, en C-long eller en C-sträng.
Ett omslags-API har lagts till för signalhanterare i Unix-stil. PyOS_getsig()
hämtar en signalhanterare och PyOS_setsig()
ställer in en ny hanterare.
Distutils: Gör det enkelt att installera moduler¶
Före Python 2.0 var det en tråkig historia att installera moduler - det fanns inget sätt att automatiskt ta reda på var Python var installerat eller vilka kompilatoralternativ som skulle användas för tilläggsmoduler. Programvaruförfattare var tvungna att gå igenom en mödosam ritual med att redigera Makefiles och konfigurationsfiler, som egentligen bara fungerar på Unix och inte stöder Windows och MacOS. Python-användare möttes av vitt skilda installationsinstruktioner som varierade mellan olika tilläggspaket, vilket gjorde det till något av en utmaning att administrera en Python-installation.
SIG för distributionsverktyg, under ledning av Greg Ward, har skapat Distutils, ett system för att göra paketinstallationen mycket enklare. De bildar paketet distutils
, en ny del av Pythons standardbibliotek. I bästa fall kräver installation av en Python-modul från källan samma steg: först betyder du helt enkelt packa upp tarball- eller zip-arkivet och kör ”python setup.py install
”. Plattformen kommer automatiskt att upptäckas, kompilatorn kommer att kännas igen, C-tilläggsmoduler kommer att kompileras och distributionen installeras i rätt katalog. Valfria kommandoradsargument ger mer kontroll över installationsprocessen, distutils-paketet erbjuder många ställen att åsidosätta standardinställningar - separera byggandet från installationen, bygga eller installera i icke-standardkataloger, med mera.
För att kunna använda Distutils måste du skriva ett setup.py
-skript. I det enkla fallet, när programvaran bara innehåller .py-filer, kan en minimal setup.py
vara bara några rader lång:
från distutils.core import setup
setup (namn = "foo", version = "1.0",
py_modules = ["modul1", "modul2"])
Filen setup.py
är inte mycket mer komplicerad om programvaran består av ett fåtal paket:
från distutils.core import setup
setup (namn = "foo", version = "1.0",
paket = ["paket", "paket.underpaket"])
Ett C-tillägg kan vara det mest komplicerade fallet; här är ett exempel hämtat från PyXML-paketet:
from distutils.core import setup, Extension
expat_extension = Extension('xml.parsers.pyexpat',
define_macros = [('XML_NS', None)],
include_dirs = [ 'extensions/expat/xmltok',
'extensions/expat/xmlparse' ],
sources = [ 'extensions/pyexpat.c',
'extensions/expat/xmltok/xmltok.c',
'extensions/expat/xmltok/xmlrole.c', ]
)
setup (name = "PyXML", version = "0.5.4",
ext_modules =[ expat_extension ] )
Distutils kan också ta hand om att skapa källkods- och binärdistributioner. Kommandot ”sdist”, som körs av ”python setup.py sdist
”, bygger en källkodsdistribution som foo-1.0.tar.gz
. Det är inte svårt att lägga till nya kommandon, kommandona ”bdist_rpm” och ”bdist_wininst” har redan bidragit för att skapa en RPM-distribution respektive en Windows-installation för programvaran. Kommandon för att skapa andra distributionsformat, t.ex. Debian-paket och Solaris .pkg
-filer, är i olika utvecklingsstadier.
Allt detta finns dokumenterat i en ny manual, Distributing Python Modules, som ansluter sig till den grundläggande Python-dokumentationen.
XML-moduler¶
Python 1.5.2 innehöll en enkel XML-parser i form av modulen xmllib
, som Sjoerd Mullender bidrog med. Sedan 1.5.2 släpptes har två olika gränssnitt för bearbetning av XML blivit vanliga: SAX2 (version 2 av Simple API for XML) tillhandahåller ett händelsedrivet gränssnitt med vissa likheter med xmllib
, och DOM (Document Object Model) tillhandahåller ett trädbaserat gränssnitt som omvandlar ett XML-dokument till ett träd med noder som kan korsas och modifieras. Python 2.0 innehåller ett SAX2-gränssnitt och ett nedbantat DOM-gränssnitt som en del av paketet xml
. Här kommer vi att ge en kort översikt över dessa nya gränssnitt; se Python-dokumentationen eller källkoden för fullständiga detaljer. Python XML SIG arbetar också med att förbättra dokumentationen.
SAX2-stöd¶
SAX definierar ett händelsestyrt gränssnitt för parsning av XML. För att använda SAX måste du skriva en SAX-hanterarklass. Hanteringsklasser ärver från olika klasser som tillhandahålls av SAX och åsidosätter olika metoder som sedan anropas av XML-parsern. Till exempel anropas metoderna startElement()
och endElement()
för varje start- och sluttagg som parsaren stöter på, metoden characters()
anropas för varje bit teckeninformation, och så vidare.
Fördelen med det händelsestyrda tillvägagångssättet är att hela dokumentet inte behöver finnas i minnet vid varje tillfälle, vilket är viktigt om du bearbetar riktigt stora dokument. Att skriva SAX-hanterarklassen kan dock bli mycket komplicerat om du försöker ändra dokumentstrukturen på något detaljerat sätt.
Det här lilla exempelprogrammet definierar till exempel en hanterare som skriver ut ett meddelande för varje start- och sluttagg och sedan analyserar filen hamlet.xml
med hjälp av den:
från xml import sax
klass SimpleHandler(sax.ContentHandler):
def startElement(self, name, attrs):
print 'Början på element:', name, attrs.keys()
def endElement(self, namn):
print "Slut på elementet:", name
# Skapa ett parser-objekt
parser = sax.make_parser()
# Berätta vilken hanterare som ska användas
handler = SimpleHandler()
parser.setContentHandler( handler )
# Parsa en fil!
parser.parse( 'hamlet.xml' )
Mer information finns i Python-dokumentationen eller i XML HOWTO på https://pyxml.sourceforge.net/topics/howto/xml-howto.html.
DOM-stöd¶
Document Object Model är en trädbaserad representation för ett XML-dokument. En toppnivå Document
-instans är roten i trädet och har ett enda barn som är toppnivå Element
-instansen. Detta Element
har barnnoder som representerar teckeninformation och eventuella underelement, som kan ha ytterligare egna barn, och så vidare. Med hjälp av DOM kan du korsa det resulterande trädet hur du vill, komma åt element- och attributvärden, infoga och ta bort noder och konvertera trädet tillbaka till XML.
DOM är användbart för att modifiera XML-dokument, eftersom du kan skapa ett DOM-träd, modifiera det genom att lägga till nya noder eller omorganisera underträd och sedan producera ett nytt XML-dokument som utdata. Du kan också konstruera ett DOM-träd manuellt och konvertera det till XML, vilket kan vara ett mer flexibelt sätt att producera XML-utdata än att bara skriva <tag1>
…</tag1>
till en fil.
Den DOM-implementering som ingår i Python finns i modulen xml.dom.minidom
. Det är en lättviktsimplementering av DOM på nivå 1 med stöd för XML-namnrymder. Bekvämlighetsfunktionerna parse()
och parseString()
tillhandahålls för att generera ett DOM-träd:
från xml.dom import minidom
doc = minidom.parse('hamlet.xml')
doc
är en Document
-instans. Document
, liksom alla andra DOM-klasser som Element
och Text
, är en underklass av basklassen Node
. Alla noder i ett DOM-träd stöder därför vissa gemensamma metoder, t.ex. toxml()
som returnerar en sträng som innehåller XML-representationen av noden och dess barn. Varje klass har också sina egna specialmetoder; till exempel har Element
och Document
en metod för att hitta alla underordnade element med ett givet taggnamn. Fortsättning från det tidigare 2-radiga exemplet:
perslist = doc.getElementsByTagName( 'PERSONA' )
print perslist[0].toxml()
print perslist[1].toxml()
För XML-filen Hamlet ger ovanstående rader följande resultat:
<PERSONA>CLAUDIUS, kung av Danmark. </PERSONA>
<PERSONA>HAMLET, son till den avlidne och brorson till den nuvarande kungen.</PERSONA>
Dokumentets rotelement finns tillgängligt som doc.documentElement
, och dess barn kan enkelt ändras genom att ta bort, lägga till eller ta bort noder:
root = doc.documentElement
# Ta bort det första barnet
root.removeChild( root.childNodes[0] )
# Flytta det nya första barnet till slutet
root.appendChild( root.childNodes[0] )
# Infoga det nya första barnet (ursprungligen,
# det tredje barnet) före det 20:e barnet.
root.insertBefore( root.childNodes[0], root.childNodes[20] )
Återigen hänvisar jag till Python-dokumentationen för en fullständig lista över de olika Node
-klasserna och deras olika metoder.
Förhållande till PyXML¶
XML Special Interest Group har arbetat med XML-relaterad Python-kod under en tid. Dess koddistribution, kallad PyXML, finns tillgänglig från SIG:s webbsidor på https://www.python.org/community/sigs/current/xml-sig. PyXML-distributionen använde också paketnamnet xml
. Om du har skrivit program som använder PyXML undrar du säkert om det är kompatibelt med paketet 2.0 xml
.
Svaret är att Python 2.0:s xml
-paket inte är kompatibelt med PyXML, men kan göras kompatibelt genom att installera en ny version av PyXML. Många applikationer kan klara sig med XML-stödet som ingår i Python 2.0, men mer komplicerade applikationer kräver att hela PyXML-paketet installeras. När PyXML version 0.6.0 eller senare installeras kommer den att ersätta xml
-paketet som levereras med Python, och kommer att vara en strikt överuppsättning av standardpaketet och lägga till en massa ytterligare funktioner. Några av de ytterligare funktionerna i PyXML inkluderar:
4DOM, en fullständig DOM-implementering från FourThought, Inc.
Den validerande parsern xmlproc, skriven av Lars Marius Garshol.
Parseracceleratormodulen
sgmlop
, skriven av Fredrik Lundh.
Moduländringar¶
Massor av förbättringar och buggfixar har gjorts i Pythons omfattande standardbibliotek; några av de berörda modulerna inkluderar readline
, ConfigParser
, cgi
, calendar
, posix
, readline
, xmllib
, aifc
, chunk
, wave
, random
, shelve
, och nntplib
. Se CVS-loggarna för exakta detaljer för varje patch.
Brian Gallew har bidragit med OpenSSL-stöd för modulen socket
. OpenSSL är en implementering av Secure Socket Layer, som krypterar data som skickas över ett uttag. När du kompilerar Python kan du redigera Modules/Setup
för att inkludera SSL-stöd, vilket lägger till en ytterligare funktion till socket
-modulen: socket.ssl(socket, keyfile, certfile)
, som tar ett socket-objekt och returnerar ett SSL-socket. Modulerna httplib
och urllib
ändrades också för att stödja https://
URL:er, även om ingen har implementerat FTP eller SMTP över SSL.
Modulen httplib
har skrivits om av Greg Stein för att stödja HTTP/1.1.
Bakåtkompatibilitet med 1.5-versionen av httplib
tillhandahålls, men för att använda HTTP/1.1-funktioner som pipelining måste koden skrivas om för att använda en annan uppsättning gränssnitt.
Modulen Tkinter
stöder nu Tcl/Tk version 8.1, 8.2 eller 8.3, och stödet för de äldre 7.x-versionerna har tagits bort. Tkinter-modulen stöder nu visning av Unicode-strängar i Tk-widgetar. Fredrik Lundh har också bidragit med en optimering som gör operationer som create_line
och create_polygon
mycket snabbare, särskilt när många koordinater används.
Modulen curses
har utökats kraftigt, med utgångspunkt från Oliver Andrichs förbättrade version, för att tillhandahålla många ytterligare funktioner från ncurses och SYSV curses, t.ex. färg, stöd för alternativa teckenuppsättningar, paddar och musstöd. Detta innebär att modulen inte längre är kompatibel med operativsystem som endast har BSD-curses, men det verkar inte finnas några operativsystem som för närvarande underhålls som faller inom denna kategori.
Som nämndes i den tidigare diskussionen om 2.0:s Unicode-stöd har den underliggande implementeringen av de reguljära uttryck som tillhandahålls av modulen re
ändrats. SRE, en ny motor för reguljära uttryck skriven av Fredrik Lundh och delvis finansierad av Hewlett Packard, stöder matchning mot både 8-bitarssträngar och Unicode-strängar.
Nya moduler¶
Ett antal nya moduler har tillkommit. Vi listar dem helt enkelt med korta beskrivningar; se 2.0-dokumentationen för detaljerna i en viss modul.
atexit
: För registrering av funktioner som ska anropas innan Python-tolken avslutas. Kod som för närvarande angersys.exitfunc
direkt bör ändras så att den istället använder modulenatexit
, importeraratexit
och anroparatexit.register()
med den funktion som ska anropas vid avslut. (Bidrag från Skip Montanaro.)codecs
,encodings
,unicodedata
: Tillagd som en del av det nya Unicode-stödet.filecmp
: Ersätter de gamla modulernacmp
,cmpcache
ochdircmp
, som nu har blivit föråldrade. (Bidrag från Gordon MacMillan och Moshe Zadka.)gettext
: Denna modul ger stöd för internationalisering (I18N) och lokalisering (L10N) för Python-program genom att tillhandahålla ett gränssnitt till meddelandekatalogbiblioteket GNU gettext. (Integrerad av Barry Warsaw, från separata bidrag av Martin von Löwis, Peter Funk och James Henstridge)linuxaudiodev
: Stöd för enheten/dev/audio
på Linux, en tvilling till den befintliga modulensunaudiodev
. (Bidrag från Peter Bosch, med korrigeringar av Jeremy Hylton.)mmap
: Ett gränssnitt för minnesmappade filer på både Windows och Unix. En fils innehåll kan mappas direkt till minnet, varvid den beter sig som en föränderlig sträng, så att dess innehåll kan läsas och ändras. De kan även skickas till funktioner som förväntar sig vanliga strängar, t.ex. modulenre
. (Bidrag från Sam Rushing, med vissa tillägg av A.M. Kuchling.)pyexpat
: Ett gränssnitt till XML-parsern Expat. (Bidrag från Paul Prescod.)robotparser
: Parsa enrobots.txt
-fil, som används för att skriva webbspindlar som artigt undviker vissa områden på en webbplats. Parsern accepterar innehållet i enrobots.txt
-fil, bygger en uppsättning regler från den och kan sedan svara på frågor om hämtbarheten för en given URL. (Bidrag från Skip Montanaro.)tabnanny
: En modul/ett skript för att kontrollera Python-källkod för tvetydig indragning. (Bidrag från Tim Peters.)UserString
: En basklass som är användbar för att härleda objekt som beter sig som strängar.webbrowser
: En modul som tillhandahåller ett plattformsoberoende sätt att starta en webbläsare på en specifik URL. För varje plattform testas olika webbläsare i en specifik ordning. Användaren kan ändra vilken webbläsare som startas genom att ställa in miljövariabeln BROWSER. (Ursprungligen inspirerad av Eric S. Raymonds patch tillurllib
som lade till liknande funktionalitet, men den slutliga modulen kommer från kod som ursprungligen implementerades av Fred Drake somTools/idle/BrowserControl.py
, och anpassades för standardbiblioteket av Fred)_winreg
: Ett gränssnitt till Windows-registret._winreg
är en anpassning av funktioner som har ingått i PythonWin sedan 1995, men som nu har lagts till i kärndistributionen och förbättrats för att stödja Unicode._winreg
skrevs av Bill Tutt och Mark Hammond.zipfile
: En modul för att läsa och skriva ZIP-formatarkiv. Det här är arkiv som produceras av PKZIP på DOS/Windows eller zip på Unix, inte att förväxla med gzip -formatfiler (som stöds av modulengzip
) (Bidrag från James C. Ahlstrom.)imputil
: En modul som ger ett enklare sätt att skriva anpassade import-hooks, jämfört med den befintliga modulenihooks
. (Implementerad av Greg Stein, med mycket diskussion på python-dev under resans gång)
IDLE Förbättringar¶
IDLE är Pythons officiella plattformsoberoende IDE, skriven med hjälp av Tkinter. Python 2.0 inkluderar IDLE 0.6, som lägger till ett antal nya funktioner och förbättringar. En partiell lista:
Förbättringar och optimeringar av användargränssnittet, särskilt när det gäller syntaxmarkering och automatisk indentation.
Klassbläddraren visar nu mer information, t.ex. funktionerna på högsta nivån i en modul.
Tabbredd är nu ett alternativ som kan ställas in av användaren. När du öppnar en befintlig Python-fil upptäcker IDLE automatiskt indragningskonventionerna och anpassar sig.
Det finns nu stöd för att anropa webbläsare på olika plattformar, som används för att öppna Python-dokumentationen i en webbläsare.
IDLE har nu en kommandorad som i stort sett liknar Pythons vaniljtolk.
Samtalstips har lagts till på många ställen.
IDLE kan nu installeras som ett paket.
I redigeringsfönstret finns det nu en rad-/kolumnrad längst ned.
Tre nya tangenttryckningskommandon: Kontrollera modul (Alt-F5), Importera modul (F5) och Kör skript (Ctrl-F5).
Borttagna och föråldrade moduler¶
Några moduler har tagits bort eftersom de är föråldrade eller för att det nu finns bättre sätt att göra samma sak. Modulen stdwin
är borta; den var för en plattformsoberoende verktygslåda för fönster som inte längre utvecklas.
Ett antal moduler har flyttats till underkatalogen lib-old
: cmp
, cmpcache
, dircmp
, dump
, find
, grep
, packmail
, poly
, util
, whatsound
, zmod
. Om du har kod som förlitar sig på en modul som har flyttats till lib-old
, kan du helt enkelt lägga till den katalogen i sys.path
för att få tillbaka dem, men du uppmanas att uppdatera all kod som använder dessa moduler.
Tack till¶
Författarna vill tacka följande personer för förslag på olika utkast till denna artikel: David Bolen, Mark Hammond, Gregg Hauser, Jeremy Hylton, Fredrik Lundh, Detlef Lannert, Aahz Maruch, Skip Montanaro, Vladimir Marangozov, Tobias Polzin, Guido van Rossum, Neil Schemenauer och Russ Schmidt.