極低碼 :https://wheart.cn
Python預裝在大多數Linux發行版上,并作為一個包提供給所有其他用戶。 但是,您可能想要使用的某些功能在發行版提供的軟件包中不可用。這時您可以從源代碼輕松編譯最新版本的Python。
如果Python沒有預先安裝并且不在發行版提供的庫中,您可以輕松地為自己使用的發行版創建包。 參閱以下鏈接:
參見
https://www.debian.org/doc/manuals/maint-guide/first.en.html
對于Debian用戶
Portal:Packaging - openSUSE Wiki
對于OpenSuse用戶
Packaging Tutorial: GNU Hello :: Fedora Docs
對于Fedora用戶
Making Packages
對于Slackware用戶
如果你想自己編譯 CPython,首先要做的是獲取 源代碼。 你可以下載最新發布版的 source 或是直接抓取最新的 clone。 (如果你想要貢獻補丁,那么你就必須先 clone。)
構建過程由常用命令組成:
./configure
make
make install
特定 Unix 平臺的 配置選項 和注意事項通常會詳細地記錄在 Python 源代碼樹的根目錄下的 README.rst 文件中。
警告
make install 可以覆蓋或偽裝 python3 二進制文件。因此,建議使用 make altinstall 而不是 make install ,因為后者只安裝了 exec_prefix/bin/pythonversion 。
這些取決于本機安裝慣例的不同;prefix 和 exec_prefix 依賴于具體安裝并且應當被解讀為針對 GNU 軟件;它們可能具有相同的含義。
例如,在大多數Linux系統上,兩者的默認值是 /usr 。
文件/目錄 | 含意 |
exec_prefix/bin/python3 | 解釋器的推薦位置 |
prefix/lib/pythonversion, exec_prefix/lib/pythonversion | 包含標準模塊的目錄的推薦位置 |
prefix/include/pythonversion, exec_prefix/include/pythonversion | 包含開發Python擴展和嵌入解釋器所需的include文件的目錄的推薦位置 |
要在Unix上使用Python腳本,需要添加可執行權限,例如:
$ chmod +x script
并在腳本的頂部放置一個合適的Shebang線。一個很好的選擇通常是:
#!/usr/bin/env python3
將在整個 PATH 中搜索Python解釋器。但是,某些Unix系統可能沒有 env 命令,因此可能需要將 /usr/bin/python3 硬編碼為解釋器路徑。
要在Python腳本中使用shell命令,請查看 subprocess 模塊。
備注
OpenSSL 的補丁發布版具有向下兼容的 ABI。 你不需要重新編譯 Python 來更新 OpenSSL。 使用一個新的版本來替代自定義 OpenSSL 安裝版就可以了。?
022 年,軟件開發者 Drew DeVault 集結 30 位工程師耗時兩年開發了一種名為 Hare(野兔)的系統編程語言,對標 C 語言,旨在構建一款“簡單、穩定和健壯”的語言。
時下,Drew DeVault 又基于 Hare 開發了一款類 Unix 操作系統,其中僅花費了 27 天的時間。以下為他的經驗分享。
原文鏈接:https://drewdevault.com/2024/05/24/2024-05-24-Bunnix.html
以下為譯文:
最近,我想要逃離“真實工作”一段時間,放松一下,所以我選擇啟動了一個新的編程項目,這個項目風險小,純粹是為了娛樂。從 4 月 21 日開始,我嘗試著用大約一個月的時間,為 x86_64 架構目標設計一個類似 Unix 的操作系統。
最終的成果就是這個 Bunnix(https://git.sr.ht/~sircmpwn/bunnix)項目。拋開因各種原因未能投入到 Bunnix 開發的時間,我實際上花了共 27 天在這個項目上。
如果你愿意,可以親自嘗試一下:
Bunnix 0.0.0 的 ISO 鏡像文件:https://cyanide.ayaya.dev/bunnix.iso
要使用 qemu(一種開源的硬件虛擬化和仿真軟件,允許用戶在一臺計算機上運行多個操作系統)啟動這個 ISO 鏡像:
qemu-system-x86_64 -cdrom bunnix.iso -display sdl -serial stdio
你也可以將 ISO 鏡像寫入 U 盤,并在硬件上啟動。我已經在 ThinkPad X220 和 Starlabs Starbook Mk IV 上進行了測試,它可能在大多數 AMD64 機器上運行良好。支持傳統啟動和 EFI 兩種方式。但有幾點限制需要注意,特別是目前還沒有 USB 支持,所以需要一個 PS/2 鍵盤(或者通過 BIOS 進行 PS/2 模擬)。大多數筆記本電腦的鍵盤默認是通過 PS/2 連接的,而通過 PS/2 模擬使用 USB 鍵盤的效果可能會有所不同。
提示:Doom(毀滅戰士游戲)的游戲按鍵設置有些特別。使用 W、A、S、D 鍵來移動,右 Shift 鍵射擊,空格鍵開門。退出游戲的功能尚未實現,所以在玩完后直接重啟即可。我得承認,在這個移植版本上我沒有花太多時間。
Bunnix 包含哪些內容?
Bunnix 內核主要由 Hare 語言編寫,同時包含一些 C 語言組件,比如用于支持 ext4 文件系統的 lwext4,以及用于內核視頻終端的 libvterm。
內核主要支持以下驅動程序:
PCI(傳統模式)
AHCI 塊設備
GPT 和 MBR 分區表
PS/2 鍵盤
平臺串行端口
CMOS 時鐘
幀緩沖區(由引導加載程序配置)
ext4 和 memfs 文件系統
此外,內核還具備眾多特性:
虛擬文件系統
/dev 目錄下預置了塊設備、、zero 和全偽設備、/dev/kbd 和 /dev/fb0、串行和視頻 TTY,以及控制終端 /dev/tty
相當完善的終端模擬器和還算過得去的 termios 支持
大約 40 個系統調用,包括但不限于 clock_gettime、poll、openat 等,以及 fork、exec、pipe、dup、dup2、ioctl 等
Bunnix 是一個單用戶系統,目前并未嘗試強制執行 Unix 文件權限和所有權,但只需再投入幾天的工作量,就相對容易地實現多用戶系統。
這個項目包含了兩個引導加載程序:
一個是兼容 multiboot、用 Hare 編寫的用于傳統啟動的引導加載程序;
另一個是用 C 語言編寫的用于 EFI 的引導加載程序。
它們都會將內核加載作為一個 ELF 文件,如果需要的話,還會加載 initramfs。EFI 引導加載程序內置了 zlib 以解壓縮 initramfs;而 multiboot 兼容的引導加載程序會為我們處理這一解壓縮過程。
用戶空間大部分由第三方源碼組裝而成,其中包括以下第三方軟件:
巨洞冒險游戲(Colossal Cave Adventure,advent)
dash shell(/bin/sh)
Doom(毀滅戰士游戲)
gzip(壓縮工具)
less(分頁查看器)
lok(基于AWK的腳本)
lolcat(使輸出文本帶有彩虹色的工具)
mandoc(手冊頁查看器)
sbase(核心實用工具集)
tcc(Tiny C Compiler)
Vim 5.7(文本編輯器)
Bunnix 所使用的 libc 庫源自 musl libc,并針對 Bunnix 的需求做了大量修改。curses 庫則是基于 netbsd-curses。
這個系統能運行但存在不少 bug,某些部分相當粗糙,用戶體驗可能差異較大。請做好系統崩潰的心理準備!
Bunnix 的誕生
我在項目的第三天開始在 Mastodon(https://fosstodon.org/@drewdevault/112319697309218275)上記錄整個過程。以下是項目進行到第三天時的情況:
接下來,分享一些關于開發 Bunnix 的思考與感悟。
Bunnix 的部分代碼來源于我早期的一個項目,名為 Helios(https://sr.ht/~sircmpwn/helios/)。以前的這個系統完成了一些相對通用 CPU 設置(如 GDT、IDT 等)的內核部分,以及支持 AHCI 這樣的驅動程序,這些功能特性被稍作調整然后融入到了 Bunnix 系統中。
我承認,如果沒有通過 Helios 項目獲得的先期經驗,Bunnix 或許不可能如此迅速地構建完成。
其中兩個比較具挑戰性的方面是 ext4 支持和虛擬終端。
為此,我引入了兩個外部依賴項 lwext4 和 libvterm。集成這兩個依賴項時,我不得不多次重寫文件系統層的代碼,雖然至今仍存在一些問題,但要實現一個正確的 Unix 文件系統設計(包括 openat 和對 inode 的良好處理),就需要比預期更深入地挖掘及研究 lwext4 的內部細節。
同時,我也學到了很多關于如何在 Hare 項目中混合使用不同源語言的知識,因為內核需要鏈接 Hare、匯編和 C 的源代碼——這種做法效果顯著,但仍有一些痛點,尤其是在構建 ABI 集成架構時。如果能自動化將 C 頭文件轉換為 Hare 的前向聲明模塊,那就太好了。Hare-c 項目中已經做了一些這方面的工作,但還有很長的路要走。如果重新開始,我可能會在設計文件系統層時更加謹慎。
正確實現終端功能也很難。我起初不確定是否要添加終端功能,但最終決定要移植 Vim,于是就這樣決定了。libvterm 是一個很棒的終端狀態機庫,但它文檔 記錄功能很差,需要大量微調才能完美集成。為了確保終端流暢運行,我還花了很多時間在性能優化上。
另一個難以準確實現的部分是調度程序。Helios 有一個比 Bunnix 更簡單的調度器,雖然我最初基于 Helios 設計了 Bunnix 的調度器,但后來不得不拋棄并重寫了很大一部分。Helios 和 Bunnix 都是單 CPU 系統,但與 Helios 不同的是,Bunnix 允許在內核中進行上下文切換,事實上,即使是搶占式
者|Lukas Gisder-Dubé
譯者|謝麗
本文將分三部分分析 JavaScript 中的錯誤,首先我們將了解錯誤的一般情況,之后,我們將關注后端(Node.js + Express.js),最后,我們將重點看下如何處理 React.js 中的錯誤。選擇這些框架,是因為它們是目前最流行的,但是,你應該也能夠將這些新發現應用到其他框架中吧!
繼上一篇文章 (https://link.medium.com/MO32x55aNR) 之后,我想談談錯誤。錯誤很好——我相信你以前聽過這個說法。乍一看,我們害怕錯誤,因為錯誤往往會涉及到在公共場合受到傷害或羞辱。通過犯錯誤,我們實際上學會了如何不去做某事,以及下次如何做得更好。
顯然,這是關于從現實生活的錯誤中學習。編程中的錯誤有點不同。它們為我們提供了很好的特征來改進我們的代碼,并告訴用戶什么地方出了問題(也可能是教他們如何修復它)。
GitHub(https://github.com/gisderdube/graceful-error-handling) 上提供了一個完整的樣例項目。
throw new Error('something went wrong')?會在 JavaScript 中創建一個錯誤實例,并停止腳本的執行,除非你對錯誤做了一些處理。當你作為 JavaScript 開發者開啟自己的職業生涯時,你自己很可能不會這樣做,但是,你已經從其他庫(或運行時)那里看到了,例如,類似“ReferenceError: fs 未定義”這樣的錯誤。
Error 對象
Error 對象有兩個內置屬性供我們使用。第一個是消息,作為參數傳遞給 Error 構造函數,例如 new Error(“這是錯誤消息”)。你可以通過 message 屬性訪問消息:
const myError=new Error(‘請改進代碼’) console.log(myError.message) // 請改進代碼
第二個是錯誤堆棧跟蹤,這個屬性非常重要。你可以通過 stack 屬性訪問它。錯誤堆棧將為你提供歷史記錄(調用堆棧),從中可以查看哪個文件導致了錯誤。堆棧的上部也包括消息,然后是實際的堆棧,從距離錯誤發生最近的點開始,一直到最外層“需要為錯誤負責”的文件:
Error: 請改進代碼 at Object.<anonymous> (/Users/gisderdube/Documents/_projects/hacking.nosync/error-handling/src/general.js:1:79) at Module._compile (internal/modules/cjs/loader.js:689:30) at Object.Module._extensions..js (internal/modules/cjs/loader.js:700:10) at Module.load (internal/modules/cjs/loader.js:599:32) at tryModuleLoad (internal/modules/cjs/loader.js:538:12) at Function.Module._load (internal/modules/cjs/loader.js:530:3) at Function.Module.runMain (internal/modules/cjs/loader.js:742:12) at startup (internal/bootstrap/node.js:266:19) at bootstrapNodeJSCore (internal/bootstrap/node.js:596:3)
拋出和處理錯誤
現在,Error 實例本身不會導致任何結果,例如,new Error('...') 不會做任何事情。當錯誤被拋出時,就會變得更有趣。然后,如前所述,腳本將停止執行,除非你在流程中以某種方式對它進行了處理。記住,是手動拋出錯誤,還是由庫拋出錯誤,甚至由運行時本身(Node 或瀏覽器),都沒有關系。讓我們看看如何在不同的場景中處理這些錯誤。
try .... catch
這是最簡單但經常被遺忘的錯誤處理方法——多虧 async / await,它的使用現在又多了起來。它可以用來捕獲任何類型的同步錯誤,例如,如果我們不把 console.log(b) 放在一個 try … catch 塊中,腳本會停止執行。
… finally
有時候,不管是否有錯誤,代碼都需要執行。你可以使用第三個可選塊 finally。通常,這與在 try…catch 語句后面加一行代碼是一樣的,但它有時很有用。
異步性——回調
異步性,這是在使用 JavaScript 時必須考慮的一個主題。當你有一個異步函數,并且該函數內部發生錯誤時,你的腳本將繼續執行,因此,不會立即出現任何錯誤。當使用回調函數處理異步函數時(不推薦),你通常會在回調函數中收到兩個參數,如下所示:
如果有錯誤,err 參數就等同于那個錯誤。如果沒有,參數將是 undefined 或 null。要么在 if(err) 塊中返回某項內容,要么將其他指令封裝在 else 塊中,這一點很重要,否則你可能會得到另一個錯誤,例如,result 可能未定義,而你試圖訪問 result.data,類似這樣的情況。
異步性——Promises
處理異步性的更好方法是使用 Promises。在這一點上,除了代碼可讀性更強之外,我們還改進了錯誤處理。只要有一個 catch 塊,我們就不再需要太關注具體的錯誤捕獲。在鏈接 Promises 時,catch 塊捕獲會自 Promises 執行或上一個 catch 塊以來的所有錯誤。注意,沒有 catch 塊的 Promises 不會終止腳本,但會給你一條可讀性較差的消息,比如:
(node:7741) UnhandledPromiseRejectionWarning: Unhandled promise rejection (rejection id: 1): Error: something went wrong (node:7741) DeprecationWarning: Unhandled promise rejections are deprecated. In the future, promise rejections that are not handled will terminate the Node.js process with a non-zero exit code. */
因此,務必要在 Promises 中加入 catch 塊。
回到 try … catch
隨著 JavaScript 引入 async / await,我們回到了最初的錯誤處理方法,借助 try … catch … finally,錯誤處理變得非常簡單。
因為這和我們處理“普通”同步錯誤的方法是一樣的,所以如果需要的話,更容易使用作用域更大的 catch 語句。
現在,我們已經有了處理錯誤的工具,讓我們看下,我們在實際情況下能用它們做什么。后端錯誤的產生和處理是應用程序至關重要的組成部分。對于錯誤處理,有不同的方法。我將向你展示一個自定義 Error 構造函數和錯誤代碼的方法,我們可以輕松地傳遞到前端或任何 API 消費者。構建后端的細節并不重要,基本思路不變。
我們將使用 Express.js 作為路由框架。讓我們考慮下最有效的錯誤處理結構。我們希望:
構建一個自定義 Error 構造函數
我們將使用已有的 Error 構造函數并擴展它。繼承在 JavaScript 中是一件危險的事情,但根據我的經驗,在這種情況下,它非常有用。我們為什么需要它?我們仍然希望堆棧跟蹤給我們一個很好的調試體驗。擴展 JavaScript 原生 Error 構造函數可以讓我們方便地獲得堆棧跟蹤。我們唯一要做的是添加代碼(我們稍后可以通過錯誤代碼訪問)和要傳遞給前端的狀態(http 狀態代碼)。
如何處理路由
在完成 Error 的自定義之后,我們需要設置路由結構。正如我指出的那樣,我們想要一個單點真錯誤處理,就是說,對于每一個路由,我們要有相同的錯誤處理行為。在默認情況下,由于路由都是封裝的,所以 Express 并不真正支持那種方式。
為了解決這個問題,我們可以實現一個路由處理程序,并把實際的路由邏輯定義為普通的函數。這樣,如果路由功能(或任何內部函數)拋出一個錯誤,它將返回到路由處理程序,然后可以傳給前端。當后端發生錯誤時,我們可以用以下格式傳遞一個響應給前端——比如一個 JSON API:
{ error: 'SOME_ERROR_CODE', description: 'Something bad happened. Please try again or contact support.' }
準備好不知所措。當我說下面的話時,我的學生總是生我的氣:
如果你咋看之下并不是什么都懂,那沒問題。只要使用一段時間,你就會發現為什么要那樣。
順便說一下,這可以稱為自上而下的學習,我非常喜歡。
路由處理程序就是這個樣子:
我希望你能讀下代碼中的注釋,我認為那比我在這里解釋更有意義。現在,讓我們看下實際的路由文件是什么樣子:
在這些例子中,我沒有做任何有實際要求的事情,我只是假設不同的錯誤場景。例如,GET /city 在第 3 行結束,POST /city 在第 8 號結束等等。這也適用于查詢參數,例如,GET /city?startsWith=R。本質上,你會有一個未處理的錯誤,前端會收到:
{ error: 'GENERIC', description: 'Something went wrong. Please try again or contact support.' }
或者你將手動拋出 CustomError,例如:
throw new CustomError('MY_CODE', 400, 'Error description')
上述代碼會轉換成:
{ error: 'MY_CODE', description: 'Error description' }
既然我們有了這個漂亮的后端設置,我們就不會再把錯誤日志泄漏到前端,而總是返回有用的信息,說明出現了什么問題。
確保你已經在 GitHub(https://github.com/gisderdube/graceful-error-handling) 上看過完整的庫。你可以把它用在任何項目中,并根據自己的需要來修改它!
下一個也是最后一個步驟是管理前端的錯誤。這里,你要使用第一部分描述的工具處理由前端邏輯產生的錯誤。不過,后端的錯誤也要顯示。首先,讓我們看看如何顯示錯誤。如前所述,我們將使用 React 進行演練。
把錯誤保存在 React 狀態中
和其他數據一樣,錯誤和錯誤消息會變化,因此,你想把它們放在組件狀態中。在默認情況下,你想要在加載時重置錯誤,以便用戶第一次看到頁面時,不會看到錯誤。
接下來我們必須澄清的是不同錯誤類型及與其匹配的可視化表示。就像在后端一樣,有 3 種類型:
2 和 3 非常類似,雖然源頭不一樣,但如果你愿意,就可以在同樣的 state 中處理。我們將從代碼中看下如何實現。
我將使用 React 的原生 state 實現,但是,你還可以使用類似 MobX 或 Redux 這樣的狀態管理系統。
全局錯誤
通常,我將把這些錯誤保存在最外層的有狀態組件中,并渲染一個靜態 UI 元素,這可能是屏幕頂部的一個紅色橫幅、模態或其他什么東西,設計實現由你決定。
讓我們看下代碼:
正如你看到的那樣,Application.js 中的狀態存在錯誤。我們也有方法可以重置并改變錯誤的值。我們把值和重置方法傳遞給 GlobalError 組件,在點擊'x'時,該組件會顯示錯誤并重置它。讓我們看看 GlobalError 組件:
你可以看到,在第 5 行,如果沒有錯誤,我們就不做任何渲染。這可以防止我們的頁面上出現一個空的紅框。當然,你可以改變這個組件的外觀和行為。例如,你可以將“x”替換為 Timeout,幾秒鐘后重置錯誤狀態。
現在,你已經準備好在任何地方使用全局錯誤狀態了,只是從 Application.js 把 _setError 向下傳遞,而且,你可以設置全局錯誤,例如,當一個請求從后端返回了字段 error: 'GENERIC'。例如:
如果你比較懶,到這里就可以結束了。即使你有具體的錯誤,你總是可以改變全局錯誤狀態,并把錯誤提示框顯示在頁面頂部。不過,我將向你展示如何處理和顯示具體的錯誤。為什么?首先,這是關于錯誤處理的權威指南,所以我不能停在這里。其次,如果你只是把所有的錯誤都作為全局錯誤來顯示,那么體驗人員會瘋掉。
處理具體的請求錯誤
和全局錯誤類似,我們也有位于其他組件內部的局部錯誤狀態,過程相同:
有件事要記住,清除錯誤通常有一個不同的觸發器。用' x '刪除錯誤是沒有意義的。關于這一點,在發出新請求時清除錯誤會更有意義。你還可以在用戶進行更改時清除錯誤,例如當修改輸入值時。
源于前端的錯誤
如前所述,這些錯誤可以使用與處理后端具體錯誤相同的方式(狀態)進行處理。這次,我們將使用一個有輸入字段的示例,只允許用戶在實際提供以下輸入時刪除一個城市:
使用錯誤代碼實現錯誤國際化
也許你一直想知道為什么我們有這些錯誤代碼,例如 GENERIC ,我們只是顯示從后端傳遞過來的錯誤描述。現在,隨著你的應用越來越大,你就會希望征服新的市場,并在某個時候面臨多種語言支持的問題。如果你到了這個時候,你就可以使用前面提到的錯誤代碼使用用戶的語言來顯示恰當的描述。
我希望你對如何處理錯誤有了一些了解。忘掉 console.error(err),它現在已經是過去時了。可以使用它進行調試,但它不應該出現在最終的產品構建中。為了防止這種情況,我建議你使用日志庫,我過去一直使用 loglevel,我對它非常滿意。
英文原文
https://levelup.gitconnected.com/the-definite-guide-to-handling-errors-gracefully-in-javascript-58424d9c60e6
*請認真填寫需求信息,我們會在24小時內與您取得聯系。