<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                ??一站式輕松地調用各大LLM模型接口,支持GPT4、智譜、豆包、星火、月之暗面及文生圖、文生視頻 廣告
                # 將 Cython 代碼移植到 PyPy > 原文: [http://docs.cython.org/en/latest/src/userguide/pypy.html](http://docs.cython.org/en/latest/src/userguide/pypy.html) Cython 對 cpyext 有基本支持,cpyext 是 [PyPy](https://pypy.org/) 中模擬 CPython 的 C-API 的層。這是通過使生成的 C 代碼在 C 編譯時適應來實現的,因此生成的代碼將在 CPython 和 PyPy 中編譯都不變。 但是,除了 Cython 可以在內部覆蓋和調整之外,cpyext C-API 仿真還涉及到 CPython 中對用戶代碼有明顯影響的真實 C-API 的一些差異。此頁面列出了主要的差異以及處理它們的方法,以便編寫在 CPython 和 PyPy 中都有效的 Cython 代碼。 ## 參考計數 PyPy 的一般設計差異是運行時內部不使用引用計數,但始終是垃圾收集器。僅通過計算 C 空間中保存的引用,僅在 cpyext 層模擬引用計數。這意味著 PyPy 中的引用計數通常與 CPython 中的引用計數不同,因為它不計算 Python 空間中保存的任何引用。 ## 對象壽命 作為不同垃圾收集特征的直接結果,對象可能會在 CPython 之外的其他點看到它們的生命周期結束。因此,當預期物體在 CPython 中死亡但在 PyPy 中可能沒有時,必須特別小心。具體來說,擴展類型(`__dealloc__()`)的解除分配器方法可能會在比 CPython 更晚的時間點被調用,而是由內存變得比被死的對象更緊密地觸發。 如果代碼中的點在某個對象應該死亡時是已知的(例如,當它與另一個對象或某個函數的執行時間相關聯時),那么值得考慮它是否可以無效并在此時手動清理而不是依賴于解除分配器。 作為副作用,這有時甚至可以導致更好的代碼設計,例如,當上下文管理器可以與`with`語句一起使用時。 ## 借用的引用和數據指針 PyPy 中的內存管理允許在內存中移動對象。 C-API 層只是 PyPy 對象的間接視圖,通常將數據或狀態復制到 C 空間,然后綁定到 C-API 對象的生命周期,而不是底層的 PyPy 對象。重要的是要理解這兩個對象在 cpyext 中是不同的東西。 效果可能是當使用數據指針或借用引用,并且不再直接從 C 空間引用擁有對象時,引用或數據指針在某些時候可能變得無效,即使對象本身仍然存在。與 CPython 相反,僅僅在列表(或其他 Python 容器)中保持對對象的引用是不夠的,因為它們的內容僅在 Python 空間中管理,因此僅引用 PyPy 對象。 Python 容器中的引用不會使 C-API 視圖保持活動狀態。 Python 類 dict 中的條目顯然也不起作用。 可能發生這種情況的一個更明顯的地方是訪問字節字符串的`char*`緩沖區。在 PyPy 中,只有在 Cython 代碼持有對字節字符串對象本身的直接引用時,這才會起作用。 另一點是當直接使用 CPython C-API 函數返回借用的引用時,例如, [`PyTuple_GET_ITEM()`](https://docs.python.org/3/c-api/tuple.html#c.PyTuple_GET_ITEM "(in Python v3.7)") 和類似的函數,但也有一些函數返回對內置模塊或運行時環境的低級對象的借用引用。 PyPy 中的 GIL 只保證借用的引用在下次調用 PyPy(或其 C-API)時保持有效,但不一定更長。 當訪問 Python 對象的內部或使用借用的引用時間長于下一次調用 PyPy 時,包括引用計數或釋放 GIL 的任何東西,因此需要在 C 空間中另外保持對這些對象的直接擁有引用,例如,在函數中的局部變量或擴展類型的屬性中。 如有疑問,請避免使用返回借用引用的 C-API 函數,或者在獲取引用和 [`Py_DECREF()`時通過對](https://docs.python.org/3/c-api/refcounting.html#c.Py_DECREF "(in Python v3.7)") [`Py_INCREF()`](https://docs.python.org/3/c-api/refcounting.html#c.Py_INCREF "(in Python v3.7)") 的一對調用顯式包圍借用引用的使用完成后將其轉換為自己的引用。 ## 內置類型,插槽和字段 以下內置類型目前在 cpyext 中不以 C 級表示形式提供: [`PyComplexObject`](https://docs.python.org/3/c-api/complex.html#c.PyComplexObject "(in Python v3.7)") , [`PyFloatObject`](https://docs.python.org/3/c-api/float.html#c.PyFloatObject "(in Python v3.7)") 和`PyBoolObject`。 內置類型的許多類型槽函數未在 cpyext 中初始化,因此不能直接使用。 類似地,幾乎沒有內置類型的(實現)特定結構域在 C 級暴露,例如 [`PyLongObject`](https://docs.python.org/3/c-api/long.html#c.PyLongObject "(in Python v3.7)") 的`ob_digit`字段或[的`allocated`字段。 `PyListObject`](https://docs.python.org/3/c-api/list.html#c.PyListObject "(in Python v3.7)") struct 等雖然容器的`ob_size`字段(`Py_SIZE()`宏使用)可用,但不保證準確。 最好不要訪問任何這些結構域和插槽,而是使用普通的 Python 類型以及對象操作的普通 Python 協議。 Cython 會將它們映射到 CPython 和 cpyext 中 C-API 的適當用法。 ## GIL 處理 目前,GIL 處理函數 [`PyGILState_Ensure()`](https://docs.python.org/3/c-api/init.html#c.PyGILState_Ensure "(in Python v3.7)") 在 PyPy 中不可重入,并且在被調用兩次時死鎖。這意味著試圖獲取 GIL“以防萬一”的代碼,因為它可能在有或沒有 GIL 的情況下被調用,但在 PyPy 中不會按預期工作。如果 GIL 已經持有,請參見 [PyGILState_Ensure 不應該死鎖。](https://bitbucket.org/pypy/pypy/issues/1778) ## 效率 簡單的函數,尤其是用于 CPython 速度的宏,可能在 cpyext 中表現出截然不同的性能特征。 返回借用引用的函數已被提及為需要特別小心,但它們也會導致更多的運行時開銷,因為它們經常在 PyPy 中創建弱引用,它們只返回 CPython 中的普通指針。可見的例子是 [`PyTuple_GET_ITEM()`](https://docs.python.org/3/c-api/tuple.html#c.PyTuple_GET_ITEM "(in Python v3.7)") 。 一些更高級別的功能也可能表現出完全不同的性能特征,例如, [`PyDict_Next()`](https://docs.python.org/3/c-api/dict.html#c.PyDict_Next "(in Python v3.7)") 用于 dict 迭代。雖然它是在 CPython 中迭代 dict 的最快方法,具有線性時間復雜度和低開銷,但它目前在 PyPy 中具有二次運行時因為它映射到正常的 dict 迭代,它無法跟蹤兩個調用之間的當前位置,因此需要在每次調用時重新啟動迭代。 這里的一般建議比 CPython 更適用,最好依靠 Cython 為您生成適當的 C-API 處理代碼,而不是直接使用 C-API - 除非您真的知道自己在做什么。如果你發現在 PyPy 和 cpyext 中做一些比 Cython 目前做得更好的方法,最好修復 Cython 以獲得每個人的好處。 ## 已知問題 * 從 PyPy 1.9 開始,在極少數情況下,子類型內置類型會導致方法調用的無限遞歸。 * 特殊方法的 Docstrings 不會傳播到 Python 空間。 * pypy3 中的 Python 3.x 改編只是慢慢開始包含 C-API,因此可以預期更多的不兼容性。 ## 錯誤和崩潰 PyPy 中的 cpyext 實現比經過充分測試的 C-API 及其在 CPython 中的底層本機實現要年輕得多且不太成熟。遇到崩潰時應記住這一點,因為問題可能并不總是存在于您的代碼或 Cython 中。此外,PyPy 及其 cpyext 實現在 C 級別比 CPython 和 Cython 更容易調試,僅僅因為它們不是為它而設計的。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看