Python е страхотен.
Изненадващо, това е доста двусмислено твърдение. Какво имам предвид под „Python'? Имам ли предвид абстрактния интерфейс на Python? Имам предвид CPython, общата реализация на Python (и да не се бърка с Cython, които са подобни в имената си)? Или имам предвид нещо друго изцяло? Може би имам предвид косвено Jython, или IronPython, или PyPy. Или може би съм стигнал до крайност и говоря за RPython или RubyPython (и двете са много, много различни неща).
Докато споменатите по-горе технологии се наричат по сходни начини и се препращат по един и същ начин, някои от тях служат на съвсем различни цели (или поне работят по съвсем различни начини).
През цялото ми време на работа с Python попаднах на тонове от тях. * Ython инструменти. Но едва наскоро отделих време да разбера какви са те, как работят и защо са необходими (по свой собствен начин).
В тази статия ще започна от нулата и ще разгледам различни реализации на Python, завършвайки с подробно въведение в PyPy, което според мен е бъдещето на езика.
Всичко започва с разбирането на това какво всъщност е „Python“.
Ако добре разбирате двоичен код, виртуални машини и други подобни, не се колебайте пропуснете тази част .
Това е често срещано объркване за начинаещите в Python.
Първото нещо, което трябва да знаете е, че „Python“ е интерфейс. Има спецификация за това какво и как трябва да прави Python Трябва дръжте се (както при всеки интерфейс). И има множество реализации (както във всеки интерфейс).
Второто нещо, което трябва да знаете е, че „интерпретиран“ и „компилиран“ са свойства на изпълнение , не един Интерфейс .
Така че въпросът всъщност не е добре оформен.
Интерпретиран ли е или компилиран ли е Python? Въпросът всъщност не е добре оформен.Това каза, че за най-честото изпълнение (CPython: написано на C, обикновено се нарича само „Python“ и със сигурност какво използвате, ако нямате представа за какво говоря), отговорът е: тълкуван , с някои части съставен. CPython компилирайте ** изходния код на python в * байт код , и в този момент тълкувам този байт код, изпълнявайки го в движение.
* Забележка: това не е „компилация“ в традиционния смисъл на думата. Обикновено казваме, че „компилирането“ взема кода на високо ниво и го преобразува в двоичен код. Но това е един вид „компилация“.
Нека разгледаме отговора малко по-отблизо, тъй като той ще ни позволи да разберем някои от понятията, които ще се появят по-късно в статията.
Много е важно да разберете разликата между байт код и двоичен (или роден) код, може би по-добре илюстриран с примери:
Накратко: двоичният код е по-бърз, но байт кодът е по-преносим и по-сигурен .
Двоичният код изглежда различно, в зависимост от вашата машина, но байт кодът изглежда еднакво на всички машини. Бихте могли да кажете, че двоичният код е оптимизиран за вашата конфигурация.
Връщайки се към CPython, процесът в набора от инструменти се случва както следва:
Начинаещите предполагат, че Python е компилиран от .pyc файловете. В това има известна истина: .pyc файлът е компилиран байт код, който след това се интерпретира. Така че, ако сте стартирали Python код и вече имате наличен .pyc файл, той ще работи по-бързо втори път, тъй като няма да е необходимо да прекомпилирате байт кода.
Както споменах по-рано, Python има няколко реализации. Отново, както споменах преди, най-често срещаният е CPython. Това е изпълнение на Python, написано на C и се счита за изпълнение по подразбиране.
Но какво да кажем за алтернативите? Един от най-известните е Jython , изпълнение в Java, което използва JVM. Докато CPython произвежда байт код, който да се изпълнява на CPython VM, Jython произвежда java байт код да се изпълнява в JVM (това е същото нещо, което се произвежда при компилиране на Java програма).
„Защо някога да използвам алтернативно изпълнение?“, Може да попитате. Ами за начало тези различни изпълнения играят добре с различни набори от технологии .
CPython улеснява писането на C разширения за вашия Python код, тъй като в крайна сметка се изпълнява от интерпретатор C. От друга страна, Jython улеснява работата с други Java програми: можете да импортирате всеки клас Java без много усилия , предизвикване и използване на вашите Java класове в рамките на вашите програми Jython. (Допълнителна бележка: ако не сте помислили подробно за това, това е лудост. Намираме се в момент, в който можете да смесвате и накъсвате различни езици и да ги компилирате в едно ядро. Ростин , програми, които смесват Fortran и C код, съществуват от известно време. Така че, разбира се, това не е непременно нещо ново. Но все пак е страхотно.)
Като пример това е валиден код на Jython:
[Java HotSpot(TM) 64-Bit Server VM (Apple Inc.)] on java1.6.0_51 >>> from java.util import HashSet >>> s = HashSet(5) >>> s.add('Foo') >>> s.add('Bar') >>> s [Foo, Bar]
IronPython е друга популярна реализация на Python, написана изцяло на C # и насочена към .NET технология. По-специално, той работи с това, което може да се нарече .NET виртуална машина, Общоезично изпълнение (CLR) от Microsoft, сравним с JVM.
разлика между s и c тип корпорация
Може да се каже, че Jython: Java :: IronPython: C #. Те се изпълняват в съответните им виртуални машини, можете да импортирате C # класове във вашия IronPython код и Java класове от вашия Jython код и т.н.
Напълно възможно е да оцелеете, без никога да докосвате внедряване на Python, който не е от CPython. Но има предимства, които се получават от промяната, много от тях зависят от технологията, която използвате. Използвате ли много езици, базирани на JVM? Jython може да е за вас. Всичко, което правите по отношение на .NET технологията? Може би трябва да опитате IronPython (а може би вече имате).
Между другото: макар че това не би било причина да се използва различна реализация, имайте предвид, че тези реализации се различават в поведението си извън начина, по който третират изходния ви код в Python. Тези разлики обаче обикновено са незначителни, разтварят се или се появяват с течение на времето, докато тези внедрения са в активно развитие. Например IronPython използвайте Unicode низове по подразбиране ; CPython обаче по подразбиране използва ASCII за версии 2.x (неуспешно с грешка в кодирането UnicodeEncodeError за не-ASCII символи), но поддържа низове Unicode по подразбиране за версии 3.x .
Така че имаме реализация на Python, написана на C, една на Java, една на C #. Логичната следваща стъпка: изпълнение на Python, написано на ... Python. (Образованият читател ще намери това обозначение за малко подвеждащо.)
Тук нещата стават объркващи. Първо, нека обсъдим компилацията Just-in-Time (JIT).
Не забравяйте, че двоичният код е много по-бърз от байт кода. Е, какво, ако можем да компилираме някои части от нашия байт код и след това да го стартираме като роден код? Ще трябва да платим някаква цена при компилиране в байт код (напр. Време), но ако резултатът е по-бърз, това би било чудесно! Това е мотивацията зад JIT компилацията, хибридна техника, която смесва предимствата на интерпретаторите и компилаторите. В основни термини JIT иска да използва компилация, за да ускори интерпретираната система.
Например, общ подход, възприет от JIT компилация:
Ето за какво е PyPy: въвеждане на JIT в Python (вж. Приложението за предишни усилия). Има, разбира се, и други цели: PyPy се стреми да бъде междуплатформен, с ниско потребление на памет и независим от всички технологии. Но JIT наистина се продава. Средно за шепа тестове за време се казва, че подобрява производителността с коефициент от 6.27 . За допълнителна дискусия вижте тази таблица на Център за скорост на PyPy :
PyPy има голям потенциал и в този момент е такъв много съвместими с CPython (като този които могат да стартират Flask, Django и т.н. ).
Но има много объркване около PyPy (вижте например това безсмислено предложение за създаване на PyPyPy ... ). Според мен това е главно защото PyPy в момента са две неща:
Интерпретатор на Python, написан на RPython (не Python (лъгал съм и преди). RPython е подмножество на Python със статични типове. В Python е ' практически невъзможно ”Строго разсъждавайте за типовете (Защо е толкова трудно? Е, помислете за факта, че:
x = random.choice([1, 'foo'])
би бил валиден код на Python (кредити към Жест ). Какъв тип е x? Как можем да разсъждаваме относно типовете променливи, когато типовете дори не се прилагат стриктно?). С RPython жертвате известна гъвкавост, но в замяна е много по-лесно да разсъждавате относно управлението на паметта и т.н., което позволява оптимизации.
Компилатор, който компилира RPython код за различни цели и добавя JIT. Платформата по подразбиране е C, например компилатор RPython-to-C, но можете също да посочите JVM и други.
Само за яснота ще ги наричам PyPy (1) и PyPy (2).
Защо ще ви трябват тези две неща и защо под един покрив? Помислете за това по следния начин: PyPy (1) е интерпретатор, написан на RPython. Така че отнема Python кода на потребителя и го компилира в байт код. Но самият интерпретатор (написан в RPython) трябва да бъде интерпретиран от друга реализация на Python, за да се изпълни, нали?
Ами ние бихме могли просто използвайте CPython за да стартирате интерпретатора. Но това не би било достатъчно бързо.
Вместо това идеята е да използваме PyPy (2) (известен още като RPython Toolchain) -RPython набор от инструменти), за да компилираме интерпретатора PyPy, за да кодираме, че друга платформа (напр. C, JVM или CLI) може да работи на нашата машина, като добавяме и JIT. Това е магия: PyPy динамично добавя JIT към интерпретатор, генерирайки свой собствен компилатор! (Отново това е лудост: ние съставяме интерпретатор и добавяме друг отделен компилатор отделно.)
В крайна сметка резултатът е самостоятелен изпълним файл, който интерпретира изходния код на Python и използва JIT оптимизациите. Което е точно това, което искахме! Това е страхотно хапване, но може би тази диаграма ще помогне:
За да повторя, истинската красота на PyPy е, че можем да напишем шепа различни интерпретатори на Python в RPython, без да се притесняваме за JIT (с изключение на няколко предложения). Тогава PyPy ще внедри JIT за нас с помощта на инструментариума RPython / PyPy (2).
Всъщност, ако станем още по-абстрактни, теоретично бихте могли да напишете преводач всякакви език, захранвайте PyPy с него и вземете JIT за този език. Това е така, защото PyPy се фокусира върху оптимизирането на текущия интерпретатор, а не върху подробностите за езика, който интерпретира.
Теоретично бихте могли да напишете интерпретатор за * всеки * език, да нахраните PyPy с него и да получите JIT за този език.Като се лутам малко, бих искал да спомена, че самият JIT е абсолютно очарователен. Той използва техника, наречена проследяване (или проследяване), която се извършва както следва :
За повече информация, този документ той е много достъпен и много интересен.
В заключение: използваме компилатора PyPy RPython-a-C (или друга платформа), за да компилираме внедрения интерпретатор PyPy RPython.
Защо е толкова готино? Защо тази луда идея си заслужава да бъде преследвана? аз мисля Алекс Гейнър той го описа много добре в своя Блог : '[PyPy е бъдещето], защото предлага по-добра скорост, повече гъвкавост и е по-добра платформа за развитие на Python.'
В обобщение:
Съдържание преведено от Пабло Фабрегат, член на TransBunko , пазар за технически преводи.