Мені дали зрозуміти, що Python - це інтерпретована мова ...
Однак, дивлячись на свій вихідний код Python, я бачу .pyc
файли, які Windows ідентифікує як "Компільовані файли Python".
Де вони заходять?
java
і javac
.
Мені дали зрозуміти, що Python - це інтерпретована мова ...
Однак, дивлячись на свій вихідний код Python, я бачу .pyc
файли, які Windows ідентифікує як "Компільовані файли Python".
Де вони заходять?
java
і javac
.
Відповіді:
Вони містять байт-код , до якого інтерпретатор Python компілює джерело. Потім цей код виконується віртуальною машиною Python.
Документація Python пояснює таке визначення:
Python - це інтерпретована мова, на відміну від складеної, хоча відмінність може бути розмитою через наявність компілятора байт-коду. Це означає, що вихідні файли можна запускати безпосередньо без явного створення виконуваного файлу, який потім запускається.
Мені дали зрозуміти, що Python - це інтерпретована мова ...
Цей популярний мем є неправильним, а точніше, побудованим на нерозумінні (природного) рівня мови: подібна помилка могла б сказати "Біблія - це тверда книга". Дозвольте мені пояснити це зображення ...
"Біблія" - це "книга" в сенсі бути класом (фактичні, фізичні об'єкти, ідентифіковані як) книги; книги, визначені як "копії Біблії", повинні мати щось основне спільне (зміст, хоча навіть вони можуть бути різними мовами, з різними прийнятними перекладами, рівнями виносок та іншими примітками) - однак ці книги є цілком дозволено відрізнятись безліччю аспектів, які не вважаються основоположними - вид палітурки, колір палітурки, шрифт (и), що використовуються для друку, ілюстрації (якщо такі є, широкі поля, що записуються чи ні, числа та види вбудованих закладок) і так далі, і так далі.
Цілком можливо, що типовий друк Біблії дійсно був би в твердій палітурці - зрештою, це книга, яка, як правило, призначена для читання знов і знов, закладена в закладки в декількох місцях, роздумуючи пошук шуканих покажчиків глави та вірша. та ін. Однак, це буденні (практичні) питання, які неможливо використати для визначення того, чи є даний фактичний об'єкт книги копією Біблії чи ні: друковані обкладинки цілком можливі!
Аналогічно, Python є "мовою" в сенсі визначення класу мовних реалізацій, які повинні бути схожими в деяких фундаментальних аспектах (синтаксис, більшість семантики, за винятком тих частин, де їм явно дозволено відрізнятись), але повністю дозволені відрізнятись майже в усіх деталях "впровадження" - включаючи те, як вони поводяться з вихідними файлами, які їм надаються, чи вони компілюють джерела в деякі форми нижчого рівня (і, якщо так, то в яку форму - і чи зберігають вони такі складені форми, на диск чи деінде), як вони виконують зазначені форми тощо.
Класичну реалізацію, CPython, часто називають просто "Python", але це лише одна з кількох реалізацій якості виробництва, поряд з IronPython Microsoft (який компілюється в CLR-коди, тобто ".NET"), Jython (який компілюється в JVM-коди), PyPy (написаний самим Python і може компілювати до величезної кількості різноманітних форм "бек-енд-енд", включаючи машинну машину, що генерується "за часом"). Вони всі Python (== "реалізація мови Python") так само, як багато поверхнево різних об'єктів книги можуть бути Бібліями (== "копіями Біблії").
Якщо вас цікавить конкретно CPython: він збирає вихідні файли у специфічну для Python форму нижчого рівня (відому як "байт-код"), робить це автоматично за потреби (коли немає файлу байт-коду, відповідного вихідному файлу, або файл байт-коду старший від вихідного або складений іншою версією Python), як правило, зберігає файли байт-коду на диску (щоб уникнути їх перекомпіляції в майбутньому). OTOH IronPython зазвичай компілює в CLR-коди (зберігаючи їх на диску чи ні, залежно) та Jython - JVM-коди (зберігаючи їх на диску чи ні - він буде використовувати .class
розширення, якщо він їх збереже).
Ці форми нижчого рівня потім виконуються відповідними "віртуальними машинами", також відомими як "інтерпретатори" - CPython VM, .Net час виконання, Java VM (відомий також як JVM).
Отже, у цьому сенсі (що роблять типові реалізації) Python - це "інтерпретована мова", якщо і лише тоді, коли є C # і Java: усі вони мають типову стратегію реалізації спочатку створення байтового коду, а потім виконання його через VM / інтерпретатор .
Більш імовірно, що увага зосереджується на тому, наскільки "важкий", повільний і високомобільний процес складання. CPython призначений для компіляції якнайшвидшого, легшого, наскільки це можливо, з якомога меншою церемонією - компілятор робить дуже мало перевірки та оптимізації помилок, тому він може працювати швидко і з невеликою кількістю пам'яті, що в свою чергу дозволяє це запускатись автоматично і прозоро, коли це потрібно, без потреби навіть не знати про те, що компіляція відбувається, більшу частину часу. Java та C # зазвичай приймають більше роботи під час компіляції (і тому не виконують автоматичну компіляцію), щоб більш ретельно перевірити помилки та виконати більше оптимізацій. Це континуум сірих лусочок, а не чорно-біла ситуація,
Немає такого поняття, як інтерпретована мова. Незалежно від того, чи використовується перекладач чи компілятор, це суто ознака реалізації та не має абсолютно нічого спільного з мовою.
Кожна мова може бути реалізована або перекладачем, або компілятором. Переважна більшість мов має щонайменше одну реалізацію кожного типу. (Наприклад, є інтерпретатори для C і C ++ і є компілятори для JavaScript, PHP, Perl, Python і Ruby.) Крім того, більшість сучасних мовних реалізацій насправді поєднують і інтерпретатор, і компілятор (або навіть декілька компіляторів).
Мова - це лише набір абстрактних математичних правил. Перекладач - одна з декількох конкретних стратегій реалізації мови. Ці двоє живуть на абсолютно різних рівнях абстракції. Якби англійська мова була набраною мовою, термін "інтерпретована мова" був би помилкою типу. Заява "Python - це інтерпретована мова" не просто хибна (тому що, якщо помилковим буде означати, що твердження навіть має сенс, навіть якщо воно неправильне), воно просто не має сенсу , оскільки мова ніколи не може бути визначена як "інтерпретовано".
Зокрема, якщо ви подивитесь на існуючі в даний час реалізації Python, це стратегії реалізації, які вони використовують:
Ви можете помітити, що кожна з реалізацій у цьому списку (плюс деякі інші, про які я не згадував, як-от tinypy, Shedskin або Psyco) має компілятор. Насправді, наскільки я знаю, в даний час не існує реалізації Python, яка є чисто інтерпретованою, не планується така реалізація і ніколи такого не було.
Термін "інтерпретована мова" не має сенсу, навіть якщо ви інтерпретуєте його як "мова з інтерпретованою реалізацією", це явно не відповідає дійсності. Хто б вам це не сказав, очевидно не знає, про що він говорить.
Зокрема, .pyc
файли, які ви бачите, - це кешовані файли байт-кодів, створені CPython, Stackless Python або Unladen Swallow.
Вони створюються інтерпретатором Python, коли .py
файл імпортується, і вони містять "компільований байт-код" імпортованого модуля / програми, ідея полягає в тому, що "переклад" з вихідного коду на байт-код (що потрібно зробити лише один раз) можна пропустити на наступних import
s, якщо файл .pyc
новіший за відповідний .py
файл, тим самим трохи прискоривши запуск. Але це все-таки інтерпретується.
Щоб прискорити завантаження модулів, Python кешує складений вміст модулів у .pyc.
CPython компілює свій вихідний код у "байт-код", і з міркувань продуктивності він кешує цей байт-код у файловій системі щоразу, коли вихідний файл має зміни. Це робить завантаження модулів Python набагато швидшим, оскільки фазу компіляції можна обійти. Коли ваш вихідний файл foo.py, CPython кешує код байта у файлі foo.pyc прямо біля джерела.
У python3 імпортне обладнання Python розширено для запису та пошуку файлів кеш-байтового коду в одному каталозі всередині кожного каталогу пакетів Python. Цей каталог буде називатися __pycache__.
Ось блок-схема, що описує завантаження модулів:
Для отримання додаткової інформації:
ref: PEP3147
ref: "Скомпільовані" файли Python
Це для початківців,
Перед запуском програми Python автоматично компілює ваш сценарій у зібраний код, так званий байт-код.
Запуск сценарію не вважається імпортом, і жоден .pyc не буде створений.
Наприклад, якщо у вас є файл скрипта abc.py, який імпортує інший модуль xyz.py , при запуску abc.py , xyz.pyc буде створений з моменту імпорту xyz, але файл abc.pyc не буде створений з абс. py не імпортується.
Якщо вам потрібно створити .pyc файл для модуля, який не імпортується, ви можете використовувати модулі py_compile
та compileall
.
py_compile
Модуль може вручну компілювати будь-який модуль. Один із способів полягає py_compile.compile
в інтерактивному використанні функції в цьому модулі:
>>> import py_compile
>>> py_compile.compile('abc.py')
Це дозволить записати .pyc в те саме місце, що і abc.py (ви можете замінити його за допомогою необов'язкового параметра cfile
).
Ви також можете автоматично компілювати всі файли в каталозі або каталогах, використовуючи модуль компіляції.
python -m compileall
Якщо ім'я каталогу (поточний каталог у цьому прикладі) опущено, модуль збирає все, що знаходиться на sys.path
Python (принаймні найпоширеніша його реалізація) слідує схемі компіляції вихідного джерела до байтових кодів, а потім інтерпретації байтових кодів на віртуальній машині. Це означає (знову ж таки, найпоширеніша реалізація) - ні чистий перекладач, ні чистий компілятор.
Інша сторона цього полягає в тому, що процес компіляції здебільшого прихований - файли .pyc в основному трактуються як кеш; вони пришвидшують справи, але вам взагалі не потрібно їх знати. Він автоматично визнає недійсним і повторно завантажує їх (повторно компілює вихідний код), коли це необхідно, виходячи зі штампів часу / дати файлу.
Приблизно тоді, коли я бачив проблему, коли компільований файл байт-коду якимось чином отримав часову позначку в майбутнє, це означало, що він завжди виглядає новіше, ніж вихідний файл. Оскільки він виглядав новішим, вихідний файл ніколи не був перекомпільований, тому які б зміни ви не внесли, вони були проігноровані ...
* .Py файл Python - це просто текстовий файл, в який ви пишете деякі рядки коду. Коли ви намагаєтеся виконати цей файл, використовуючи скажіть "python filename.py"
Ця команда викликає віртуальну машину Python. Віртуальна машина Python має 2 компоненти: "компілятор" та "інтерпретатор". Інтерпретатор не може безпосередньо прочитати текст у файлі * .py, тому цей текст спочатку перетворюється в байт-код, націлений на PVM (не апаратний, а PVM) . PVM виконує цей байт-код. * .pyc-файл також генерується, як частина запуску його, який виконує операцію імпорту на файл у оболонці або в іншому файлі.
Якщо цей файл * .pyc вже генерується, то при кожному наступному запуску / виконанні файлу * .py система безпосередньо завантажує файл * .pyc, який не потребує компіляції (це заощадить деякі машинні цикли процесора).
Після генерування файлу * .pyc немає необхідності у файлі * .py, якщо ви його не редагуєте.