主頁 > 後端開發 > Python 相關檔案常見的后綴名詳解

Python 相關檔案常見的后綴名詳解

2021-05-04 09:02:02 後端開發

常見的 Python 檔案后綴有:pypycpyopyipywpydpyx 等,

本文只介紹相對常見的一些后綴名,至于一些特別冷門的檔案格式,例如一些文章提到的pyzpywzrpypydepyppyt等,并沒有進行研究,因為這些擴展名資料很少,網上搜到的文章似乎都是同一個出處,只是簡單提了一句,說了等于沒說,

py

最常見的 Python 源代碼檔案,

實際上如果用 python + 檔案 的方式運行代碼,只要檔案內容相同,后綴名是不重要的,也就是說下面的運行結果都是等價的:

python test.py
python test.txt
python test

pyc

常見的 Python 位元組碼快取檔案,

pyc檔案和py檔案一樣,都可以直接執行,下面的運行結果都是等價的:

python test.py
python test.pyc
作用一:提升加載性能

我們知道 Python 代碼在執行時,會先由 Python 決議器翻譯成 PyCodeObject 物件,俗稱位元組碼 (Byte code),然后交給 Python 解釋器來執行位元組碼,

上述程序中翻譯后的位元組碼是保存在記憶體中,程式運行結束就沒了,而代碼沒有修改的情況下,每次生成的位元組碼是一樣的,所以每次跑程式都再走一遍翻譯位元組碼的程序有點浪費性能,因此為了提高加載效率,Python 在程式執行結束后會把每個檔案的位元組碼寫入到硬碟中保存為 xxx.pyc 檔案,這樣下一次再執行這個程式時先在目錄下找有沒有xxx.pyc 檔案,如果有這個對應檔案且修改時間和xxx.py 檔案的修改時間一樣,就不用再執行翻譯成位元組碼的程序,直接讀取xxx.pyc 檔案執行,其實快取pyc 檔案的方式對性能的提升很微小,只有專案檔案非常多的時候才能看到顯著提升,

默認情況下,我們發現并不是所有的py 檔案都會自動生成pyc 檔案,只有被其他檔案 import 過的檔案才會生成對應的pyc 檔案,可能 Python 認為被 import 的檔案重復使用的概率比較高,而主檔案一般只需要加載一次,

簡單做個實驗可以驗證,新建兩個 Python 檔案hello.pyimport.py,內容如下:

# hello.py
print("hello")
# import.py
impot hello

直接運行 python hello.py,并沒有生成pyc 檔案,而運行python import.py,在當前目錄下生成了hello.py對應的pyc 檔案,

這里 Python2 和 Python3 有些不同, Python2 是直接在當前目錄下生成同名 pyc 檔案,Python3 是在當前目錄下創建了__pycache__檔案夾,然后在檔案夾內創建了一個包含 Python 版本資訊的xxx.cpython-37.pyc 檔案,

Python2
在這里插入圖片描述
Python3
在這里插入圖片描述

作用二:隱藏源代碼

pyc格式是給解釋器看的二進制檔案,直接用編輯器打開看上去是亂碼,所以將 Python 代碼先編譯成pyc檔案再交付給別人使用,一定程度上實作隱藏源代碼的效果,

默認情況下,主檔案不會生成pyc檔案,可以通過 Python 自帶的py_compilecompileall 庫,手動將所有py檔案"編譯"成pyc檔案,

python -m py_compile *.py
python -m compileall *.py

Python2
在這里插入圖片描述
Python3
在這里插入圖片描述

反編譯 pyc

前面說了,是“一定程度上實作隱藏源代碼的效果”,其實可以通過反編譯pyc檔案來獲得py原始碼,而且反編譯的難度并不大,

uncompyle6是一個專門用于將pyc反編譯為py原始碼的第三方庫,安裝方式:

pip install uncompyle6

執行下面命令可以將剛才生成的pyc反編譯為py檔案:

uncompyle6 -o . *.pyc

在這里插入圖片描述
打開生成的檔案hello.cpython-37.pyimport.cpython-37.py,可以看到和之前的py代碼內容一模一樣,不過多了一些 Python 的版本資訊,
在這里插入圖片描述
魔高一尺,道高一丈,有反編譯技術就有防止反編譯技術,更多了解參見這篇文章:通過位元組碼混淆來保護Python代碼,

pyo

優化后的 Python 位元組碼快取檔案,

pyo檔案的作用和pyc檔案沒啥區別,唯一的優化就是去掉了斷言陳述句,即assert陳述句,官方檔案描述:

When the Python interpreter is invoked with the -O flag, optimized code is generated and stored in .pyo files. The optimizer currently doesn’t help much; it only removes assert statements. When -O is used, all bytecode is optimized; .pyc files are ignored and .py files are compiled to optimized bytecode.

同樣可以利用py_compilecompileall 庫將上面示例的兩個檔案編譯成pyo檔案,只是多加一個引數-O,運行結果也沒有任何變化:

python -O -m py_compile *.py
python -O -m compileall *.py

在這里插入圖片描述
從 Python3.5 開始,Python 只使用 pyc 而不再使用pyo,所以下面命令也無法生成 pyo檔案,生成的依然是 pyc 檔案:

python3 -O -m py_compile *.py
python3 -O -m compileall *.py

在這里插入圖片描述

pyi

Python 的存根檔案,用于代碼檢查時的型別提示,

pyi檔案是PEP484提案規定的一種用于 Python 代碼型別提示(Type Hints)的檔案,PEPPython Enhancement Proposals,是經過 Python 社區核心開發者討論并一致同意后,對外發布的一些正式規范檔案,例如我們常說的Python之禪(PEP20),代碼風格 PEP8 格式化(PEP8),將 print 改為函式(PEP3105)等,關于PEP的更多了解見這篇文章:學習Python,怎能不懂點PEP呢?,

常用的 IDE 都會有型別檢查提示功能,比如在 PyCharm 中,當我們給一個函式傳入一個錯誤的型別時會給出對應的提示,這其實不是 IDE 的特殊開發的功能,它只是集成了PEP484的規定,利用了已經預先生成好的 pyi檔案,

舉個例子,os.makedirs是標準庫中用于創建檔案夾路徑的函式,它的入參應該是一個字串型別,如果傳入一個 int 型別,IDE 會立刻給出提示,
在這里插入圖片描述
按住ctrl點進去,進入到 os 模塊定義os.makedirs的地方,發現前面有個*號,滑鼠放上去會提示Has stub item in __init__.pyi
在這里插入圖片描述
點擊*號就會跳到對應的__init__.pyi檔案,這個檔案里按照PEP484規定,為os模塊每個函式都定義了對應的型別檢查規則,
在這里插入圖片描述
關于pyi檔案的定義規則以及自己如何生成,詳見官方檔案:PEP 484 – Type Hints

pyw

一種 Python 源代碼檔案,一般只存在于 Windows 系統,

pyw檔案和py檔案除了后綴名不一樣之外沒有任何區別,兩者都是 Python 原始碼檔案,前面 py那一節說過“如果用 python + 檔案 的方式運行代碼,只要檔案內容相同,后綴名是不重要的”,這一點在 Windows 系統和 Linux 系統都是一樣的,

Windows 系統,新建兩個內容相同的 Python 檔案hello.pyhello.pyw,用python + 檔案 的方式運行,結果一樣:

# hello.py
print("hello")
# hello.pyw
print("hello")

在這里插入圖片描述
那為什么還要有pyw檔案呢?

在Windows 系統上雙擊檔案時,系統會根據檔案擴展名來呼叫關聯的exe程式來運行這個檔案,打開 Python 安裝目錄,可以看到有python.exepythonw.exe兩個exe,其中python.exe關聯了py檔案,pythonw.exe關聯了pyw檔案,跟 python.exe 相比,pythonw.exe運行時不會彈出控制臺視窗, stdout 、stderr 和 stdin 都無效,所以像 print 這種把內容輸出到 stdout 的操作就不會有列印結果(cmd 視窗都沒有了也沒有地方顯示了),
在這里插入圖片描述
所以在用 Python 開發 GUI 程式時,如果不想讓程式運行的時候彈出一個黑乎乎的 cmd 框,就可以將原始碼檔案后綴名改為pyw格式,但是我感覺這個pww格式用處并不大,實際使用很少有人雙擊py或者pyw檔案來運行 Python 代碼,我之前曾用tkinter開發過帶 Windows 界面的 Python 程式,當時是通過雙擊 bat腳本啟動 Python 腳本同時關閉 cmd 界面框,來避免彈出黑框框的,

pyd

Python 可直接呼叫的 C 語言元件檔案,一般只存在于 Windows 系統,

Python 是一種膠水語言,我們可以將對速度要求比較高的那一部分代碼使用 C 語言撰寫,編譯成元件檔案,再通過 Python 來呼叫,一般來說,在 Linux 上是 so檔案,在 Windows 系統上是DLL檔案,

例如有一個 C 語言撰寫的 Windows 元件 test_lib.dll,編譯前的代碼如下:

int sum(int x, int y)
{
    return x + y;
}

我們可以在 Python 代碼中通過下面的方式來呼叫

# test_lib.dll 放在當前目錄下
import ctypes
from ctypes import *

test_lib = ctypes.windll.LoadLibrary("test_lib.dll")
a = ctypes.c_int(1)
b = ctypes.c_int(2)
out = test_lib.sum(a, b)
print(out) # 3

在 Windows 系統上,Python 還有一種 pyd格式的元件,上面的呼叫方式是先通過ctypes.windll.LoadLibrary 方法將元件加載進來,而pyd格式就可以在 Python 代碼中直接import進來,類似下面這樣:

# test_lib.pyd 放在當前目錄下
import test_lib

out = test_lib.sum(1, 2)
print(out) # 3

關于 pyd檔案和dll檔案的區別,可參考官方檔案的說明:

Is a *.pyd file the same as a DLL?

Yes, .pyd files are dll’s, but there are a few differences. If you have a DLL named foo.pyd, then it must have a function PyInit_foo(). You can then write Python “import foo”, and Python will search for foo.pyd (as well as foo.py, foo.pyc) and if it finds it, will attempt to call PyInit_foo() to initialize it. You do not link your .exe with foo.lib, as that would cause Windows to require the DLL to be present.

Note that the search path for foo.pyd is PYTHONPATH, not the same as the path that Windows uses to search for foo.dll. Also, foo.pyd need not be present to run your program, whereas if you linked your program with a dll, the dll is required. Of course, foo.pyd is required if you want to say import foo. In a DLL, linkage is declared in the source code with __declspec(dllexport). In a .pyd, linkage is defined in a list of available functions.

C 語言代碼和 Python 代碼都可以通過一定的方法編譯成pyd格式的檔案,本人并沒有實際使用過pyd檔案,詳細方法可參考下面的文章:

使用C++創建Pyd檔案擴展Python模塊

Python源代碼保護(Python檔案編譯生成pyd/so庫檔案)

pyx

Cython 源代碼檔案,

注意是 Cython 不是 CPython,Cython 可以說是一種編程語言, 它結合了Python 的語法和有 C/C++的效率,用 Cython 寫完的代碼可以很容易轉成 C 語言代碼,然后又可以再編譯成元件(pyddll)供 Python 呼叫,所以 Cython 一般用來撰寫 Python 的 C 擴展,上面說的 Python 檔案編譯生成 pyd 檔案就是利用 Cython 來實作的 ,Cython 的源代碼檔案一般為pyx后綴,

總結

后綴名作用
py最常見的 Python 源代碼檔案,
pyc常見的 Python 位元組碼快取檔案,可以反編譯成 py 檔案,
pyo另一種 Python 位元組碼快取檔案,只存在于 Python2 及 Python3.5 之前的版本,
pyiPython 的存根檔案,常用于 IDE 代碼格式檢查時的型別提示,
pyw另一種 Python 源代碼檔案,一般只存在于 Windows 系統,
pyd一種 Python 可直接呼叫的 C 語言元件檔案,一般只存在于 Windows 系統,
pyxCython 源代碼檔案,一般用來撰寫 Python 的 C 擴展,

轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/282628.html

標籤:python

上一篇:大一就開始這樣刷題后,我成了同學們眼中的 offer 收割機

下一篇:python中必須要會的四大高級資料型別(字符,元組,串列,字典)

標籤雲
其他(157675) Python(38076) JavaScript(25376) Java(17977) C(15215) 區塊鏈(8255) C#(7972) AI(7469) 爪哇(7425) MySQL(7132) html(6777) 基礎類(6313) sql(6102) 熊猫(6058) PHP(5869) 数组(5741) R(5409) Linux(5327) 反应(5209) 腳本語言(PerlPython)(5129) 非技術區(4971) Android(4554) 数据框(4311) css(4259) 节点.js(4032) C語言(3288) json(3245) 列表(3129) 扑(3119) C++語言(3117) 安卓(2998) 打字稿(2995) VBA(2789) Java相關(2746) 疑難問題(2699) 细绳(2522) 單片機工控(2479) iOS(2429) ASP.NET(2402) MongoDB(2323) 麻木的(2285) 正则表达式(2254) 字典(2211) 循环(2198) 迅速(2185) 擅长(2169) 镖(2155) 功能(1967) .NET技术(1958) Web開發(1951) python-3.x(1918) HtmlCss(1915) 弹簧靴(1913) C++(1909) xml(1889) PostgreSQL(1872) .NETCore(1853) 谷歌表格(1846) Unity3D(1843) for循环(1842)

熱門瀏覽
  • 【C++】Microsoft C++、C 和匯編程式檔案

    ......

    uj5u.com 2020-09-10 00:57:23 more
  • 例外宣告

    相比于斷言適用于排除邏輯上不可能存在的狀態,例外通常是用于邏輯上可能發生的錯誤。 例外宣告 Item 1:當函式不可能拋出例外或不能接受拋出例外時,使用noexcept 理由 如果不打算拋出例外的話,程式就會認為無法處理這種錯誤,并且應當盡早終止,如此可以有效地阻止例外的傳播與擴散。 示例 //不可 ......

    uj5u.com 2020-09-10 00:57:27 more
  • Codeforces 1400E Clear the Multiset(貪心 + 分治)

    鏈接:https://codeforces.com/problemset/problem/1400/E 來源:Codeforces 思路:給你一個陣列,現在你可以進行兩種操作,操作1:將一段沒有 0 的區間進行減一的操作,操作2:將 i 位置上的元素歸零。最終問:將這個陣列的全部元素歸零后操作的最少 ......

    uj5u.com 2020-09-10 00:57:30 more
  • UVA11610 【Reverse Prime】

    本人看到此題沒有翻譯,就附帶了一個自己的翻譯版本 思考 這一題,它的第一個要求是找出所有 $7$ 位反向質數及其質因數的個數。 我們應該需要質數篩篩選1~$10^{7}$的所有數,這里就不慢慢介紹了。但是,重讀題,我們突然發現反向質數都是 $7$ 位,而將它反過來后的數字卻是 $6$ 位數,這就說明 ......

    uj5u.com 2020-09-10 00:57:36 more
  • 統計區間素數數量

    1 #pragma GCC optimize(2) 2 #include <bits/stdc++.h> 3 using namespace std; 4 bool isprime[1000000010]; 5 vector<int> prime; 6 inline int getlist(int ......

    uj5u.com 2020-09-10 00:57:47 more
  • C/C++編程筆記:C++中的 const 變數詳解,教你正確認識const用法

    1、C中的const 1、區域const變數存放在堆疊區中,會分配記憶體(也就是說可以通過地址間接修改變數的值)。測驗代碼如下: 運行結果: 2、全域const變數存放在只讀資料段(不能通過地址修改,會發生寫入錯誤), 默認為外部聯編,可以給其他源檔案使用(需要用extern關鍵字修飾) 運行結果: ......

    uj5u.com 2020-09-10 00:58:04 more
  • 【C++犯錯記錄】VS2019 MFC添加資源不懂如何修改資源宏ID

    1. 首先在資源視圖中,添加資源 2. 點擊新添加的資源,復制自動生成的ID 3. 在解決方案資源管理器中找到Resource.h檔案,編輯,使用整個專案搜索和替換的方式快速替換 宏宣告 4. Ctrl+Shift+F 全域搜索,點擊查找全部,然后逐個替換 5. 為什么使用搜索替換而不使用屬性視窗直 ......

    uj5u.com 2020-09-10 00:59:11 more
  • 【C++犯錯記錄】VS2019 MFC不懂的批量添加資源

    1. 打開資源頭檔案Resource.h,在其中預先定義好宏 ID(不清楚其實ID值應該設定多少,可以先新建一個相同的資源項,再在這個資源的ID值的基礎上遞增即可) 2. 在資源視圖中選中專案資源,按F7編輯資源檔案,按 ID 型別 相對路徑的形式添加 資源。(別忘了先把檔案拷貝到專案中的res檔案 ......

    uj5u.com 2020-09-10 01:00:19 more
  • C/C++編程筆記:關于C++的參考型別,專供新手入門使用

    今天要講的是C++中我最喜歡的一個用法——參考,也叫別名。 參考就是給一個變數名取一個變數名,方便我們間接地使用這個變數。我們可以給一個變數創建N個參考,這N + 1個變數共享了同一塊記憶體區域。(參考型別的變數會占用記憶體空間,占用的記憶體空間的大小和指標型別的大小是相同的。雖然參考是一個物件的別名,但 ......

    uj5u.com 2020-09-10 01:00:22 more
  • 【C/C++編程筆記】從頭開始學習C ++:初學者完整指南

    眾所周知,C ++的學習曲線陡峭,但是花時間學習這種語言將為您的職業帶來奇跡,并使您與其他開發人員區分開。您會更輕松地學習新語言,形成真正的解決問題的技能,并在編程的基礎上打下堅實的基礎。 C ++將幫助您養成良好的編程習慣(即清晰一致的編碼風格,在撰寫代碼時注釋代碼,并限制類內部的可見性),并且由 ......

    uj5u.com 2020-09-10 01:00:41 more
最新发布
  • Rust中的智能指標:Box<T> Rc<T> Arc<T> Cell<T> RefCell<T> Weak

    Rust中的智能指標是什么 智能指標(smart pointers)是一類資料結構,是擁有資料所有權和額外功能的指標。是指標的進一步發展 指標(pointer)是一個包含記憶體地址的變數的通用概念。這個地址參考,或 ” 指向”(points at)一些其 他資料 。參考以 & 符號為標志并借用了他們所 ......

    uj5u.com 2023-04-20 07:24:10 more
  • Java的值傳遞和參考傳遞

    值傳遞不會改變本身,參考傳遞(如果傳遞的值需要實體化到堆里)如果發生修改了會改變本身。 1.基本資料型別都是值傳遞 package com.example.basic; public class Test { public static void main(String[] args) { int ......

    uj5u.com 2023-04-20 07:24:04 more
  • [2]SpinalHDL教程——Scala簡單入門

    第一個 Scala 程式 shell里面輸入 $ scala scala> 1 + 1 res0: Int = 2 scala> println("Hello World!") Hello World! 檔案形式 object HelloWorld { /* 這是我的第一個 Scala 程式 * 以 ......

    uj5u.com 2023-04-20 07:23:58 more
  • 理解函式指標和回呼函式

    理解 函式指標 指向函式的指標。比如: 理解函式指標的偽代碼 void (*p)(int type, char *data); // 定義一個函式指標p void func(int type, char *data); // 宣告一個函式func p = func; // 將指標p指向函式func ......

    uj5u.com 2023-04-20 07:23:52 more
  • Django筆記二十五之資料庫函式之日期函式

    本文首發于公眾號:Hunter后端 原文鏈接:Django筆記二十五之資料庫函式之日期函式 日期函式主要介紹兩個大類,Extract() 和 Trunc() Extract() 函式作用是提取日期,比如我們可以提取一個日期欄位的年份,月份,日等資料 Trunc() 的作用則是截取,比如 2022-0 ......

    uj5u.com 2023-04-20 07:23:45 more
  • 一天吃透JVM面試八股文

    什么是JVM? JVM,全稱Java Virtual Machine(Java虛擬機),是通過在實際的計算機上仿真模擬各種計算機功能來實作的。由一套位元組碼指令集、一組暫存器、一個堆疊、一個垃圾回收堆和一個存盤方法域等組成。JVM屏蔽了與作業系統平臺相關的資訊,使得Java程式只需要生成在Java虛擬機 ......

    uj5u.com 2023-04-20 07:23:31 more
  • 使用Java接入小程式訂閱訊息!

    更新完微信服務號的模板訊息之后,我又趕緊把微信小程式的訂閱訊息給實作了!之前我一直以為微信小程式也是要企業才能申請,沒想到小程式個人就能申請。 訊息推送平臺🔥推送下發【郵件】【短信】【微信服務號】【微信小程式】【企業微信】【釘釘】等訊息型別。 https://gitee.com/zhongfuch ......

    uj5u.com 2023-04-20 07:22:59 more
  • java -- 緩沖流、轉換流、序列化流

    緩沖流 緩沖流, 也叫高效流, 按照資料型別分類: 位元組緩沖流:BufferedInputStream,BufferedOutputStream 字符緩沖流:BufferedReader,BufferedWriter 緩沖流的基本原理,是在創建流物件時,會創建一個內置的默認大小的緩沖區陣列,通過緩沖 ......

    uj5u.com 2023-04-20 07:22:49 more
  • Java-SpringBoot-Range請求頭設定實作視頻分段傳輸

    老實說,人太懶了,現在基本都不喜歡寫筆記了,但是網上有關Range請求頭的文章都太水了 下面是抄的一段StackOverflow的代碼...自己大修改過的,寫的注釋挺全的,應該直接看得懂,就不解釋了 寫的不好...只是希望能給視頻網站開發的新手一點點幫助吧. 業務場景:視頻分段傳輸、視頻多段傳輸(理 ......

    uj5u.com 2023-04-20 07:22:42 more
  • Windows 10開發教程_編程入門自學教程_菜鳥教程-免費教程分享

    教程簡介 Windows 10開發入門教程 - 從簡單的步驟了解Windows 10開發,從基本到高級概念,包括簡介,UWP,第一個應用程式,商店,XAML控制元件,資料系結,XAML性能,自適應設計,自適應UI,自適應代碼,檔案管理,SQLite資料庫,應用程式到應用程式通信,應用程式本地化,應用程式 ......

    uj5u.com 2023-04-20 07:22:35 more