Python在Windows上的常見問題?

我怎樣在Windows下運行一個Python程序??

這不一定是一個簡單的問題。如果你已經(jīng)熟悉在Windows的命令行中運行程序的方法,一切都顯而易見;不然的話,你也許需要額外獲得些許指導(dǎo)。

Unless you use some sort of integrated development environment, you will end up typing Windows commands into what is referred to as a "Command prompt window". Usually you can create such a window from your search bar by searching for cmd. You should be able to recognize when you have started such a window because you will see a Windows "command prompt", which usually looks like this:

C:\>

前面的字母可能會不同,而且后面有可能會有其他東西,所以你也許會看到類似這樣的東西:

D:\YourName\Projects\Python>

出現(xiàn)的內(nèi)容具體取決與你的電腦如何設(shè)置和最近用它做的事。 當(dāng)你啟動了這樣一個窗口后,就可以開始運行Python程序了。

Python 腳本需要被另外一個叫做 Python 解釋器 的程序來處理。 解釋器讀取腳本,把它編譯成字節(jié)碼,然后執(zhí)行字節(jié)碼來運行你的程序。 所以怎樣安排解釋器來處理你的 Python 腳本呢?

首先,確保命令窗口能夠?qū)ⅰ皃y”識別為指令來開啟解釋器。 如果你打開過一個命令窗口, 嘗試輸入命令 py 然后按回車:

C:\Users\YourName> py

然后你應(yīng)當(dāng)看見類似類似這樣的東西:

Python 3.6.4 (v3.6.4:d48eceb, Dec 19 2017, 06:04:45) [MSC v.1900 32 bit (Intel)] on win32
Type "help", "copyright", "credits" or "license" for more information.
>>>

解釋器已經(jīng)以“交互模式”打開。這意味著你可以交互輸入Python語句或表達(dá)式,并在等待時執(zhí)行或評估它們。這是Python最強大的功能之一。輸入幾個表達(dá)式并看看結(jié)果:

>>>
>>> print("Hello")
Hello
>>> "Hello" * 3
'HelloHelloHello'

許多人把交互模式當(dāng)作方便和高度可編程的計算器。 想結(jié)束交互式Python會話時,調(diào)用 exit() 函數(shù),或者按住 Ctrl 鍵時輸入 Z ,之后按 Enter 鍵返回Windows命令提示符。

你可能發(fā)現(xiàn)在開始菜單有這樣一個條目 開始 ? 所有程序 ? Python 3.x ? Python (命令行), 運行它后會出現(xiàn)一個有著 >>> 提示的新窗口。 在此之后,如果調(diào)用 exit() 函數(shù)或按 Ctrl-Z 組合鍵后窗口將會消失。 Windows 會在這個窗口中運行一個“python”命令,并且在你終止解釋器的時候關(guān)閉它。

現(xiàn)在我們知道 py 命令已經(jīng)被識別,可以輸入 Python 腳本了。 你需要提供 Python 腳本的絕對路徑或相對路徑。 假設(shè) Python 腳本位于桌面上并命名為 hello.py,并且命令提示符在用戶主目錄打開,那么可以看到類似于這樣的東西:

C:\Users\YourName>

那么現(xiàn)在可以讓 py 命令執(zhí)行你的腳本,只需要輸入 py 和腳本路徑:

C:\Users\YourName> py Desktop\hello.py
hello

我怎么讓 Python 腳本可執(zhí)行??

在 Windows 上,標(biāo)準(zhǔn) Python 安裝程序已將 .py 擴展名與文件類型 (Python.File) 相關(guān)聯(lián),并為該文件類型提供運行解釋器的打開命令 (D:\Program Files\Python\python.exe "%1" %*) 。 這足以使腳本在命令提示符下作為“foo.py”命令被執(zhí)行。 如果希望通過簡單地鍵入“foo”而無需輸入文件擴展名來執(zhí)行腳本,則需要將 .py 添加到 PATHEXT 環(huán)境變量中。

為什么有時候 Python 程序會啟動緩慢??

通常,Python 在 Windows 上啟動得很快,但偶爾會有錯誤報告說 Python 突然需要很長時間才能啟動。更令人費解的是,在其他配置相同的 Windows 系統(tǒng)上,Python 卻可以工作得很好。

該問題可能是由于計算機上的殺毒軟件配置錯誤造成的。當(dāng)將病毒掃描配置為監(jiān)視文件系統(tǒng)中所有讀取行為時,一些殺毒掃描程序會導(dǎo)致兩個數(shù)量級的啟動開銷。請檢查你系統(tǒng)安裝的殺毒掃描程序的配置,確保兩臺機它們是同樣的配置。已知的, McAfee 殺毒軟件在將它設(shè)置為掃描所有文件系統(tǒng)訪問時,會產(chǎn)生這個問題。

我怎樣使用 Python 腳本制作可執(zhí)行文件??

請參閱 如何由 Python 腳本創(chuàng)建能獨立運行的二進(jìn)制程序? 查看可用來生成可執(zhí)行文件的工具清單。

*.pyd 文件和 DLL 文件相同嗎??

是的, .pyd 文件也是 dll ,但有一些差異。如果你有一個名為 foo.pyd 的DLL,那么它必須有一個函數(shù) PyInit_foo() 。 然后你可以編寫 Python 代碼 “import foo” ,Python 將搜索 foo.pyd (以及 foo.py 、 foo.pyc )。如果找到它,將嘗試調(diào)用 PyInit_foo() 來初始化它。你不應(yīng)將 .exe 與 foo.lib 鏈接,因為這會導(dǎo)致 Windows 要求存在 DLL 。

請注意, foo.pyd 的搜索路徑是 PYTHONPATH ,與 Windows 用于搜索 foo.dll 的路徑不同。此外, foo.pyd 不需要存在來運行你的程序,而如果你將程序與 dll 鏈接,則需要 dll 。 當(dāng)然,如果你想 import foo ,則需要 foo.pyd 。在 DLL 中,鏈接在源代碼中用 __declspec(dllexport) 聲明。 在 .pyd 中,鏈接在可用函數(shù)列表中定義。

我怎樣將 Python 嵌入一個 Windows 程序??

在 Windows 應(yīng)用程序中嵌入 Python 解釋器可以總結(jié)如下:

  1. 請 _不要_ 直接在你的 .exe 文件中內(nèi)置 Python 。在 Windows 上, Python 必須是一個 DLL ,這樣才可以處理導(dǎo)入的本身就是 DLL 的模塊。(這是第一個未記錄的關(guān)鍵事實。)相反,鏈接到 pythonNN.dll ;它通常安裝在 C:\Windows\System 中。 NN 是 Python 版本,如數(shù)字“33”代表 Python 3.3 。

    你可以通過兩種不同的方式鏈接到 Python 。加載時鏈接意味著鏈接到 pythonNN.lib ,而運行時鏈接意味著鏈接 pythonNN.dll 。(一般說明: python NN.lib 是所謂的“import lib”,對應(yīng)于 pythonNN.dll 。它只定義了鏈接器的符號。)

    運行時鏈接極大地簡化了鏈接選項,一切都在運行時發(fā)生。你的代碼必須使用 Windows 的 LoadLibraryEx() 程序加載 pythonNN.dll 。代碼還必須使用使用 Windows 的 GetProcAddress() 例程獲得的指針訪問 pythonNN.dll 中程序和數(shù)據(jù)(即 Python 的 C API )。宏可以使這些指針對任何調(diào)用 Python C API 中的例程的 C 代碼都是透明的。

  2. 如果你使用 SWIG ,很容易創(chuàng)建一個 Python “擴展模塊”,它將使應(yīng)用程序的數(shù)據(jù)和方法可供 Python 使用。SWIG將為你處理所有蹩腳的細(xì)節(jié)。結(jié)果是你將鏈接到 .exe 文件 的C代碼 (!) 你不必創(chuàng)建 DLL 文件,這也簡化了鏈接。

  3. SWIG 將創(chuàng)建一個 init 函數(shù)(一個 C 函數(shù)),其名稱取決于擴展模塊的名稱。例如,如果模塊的名稱是 leo ,則 init 函數(shù)將被稱為 initleo() 。 如果您使用 SWIG 陰影類,則 init 函數(shù)將被稱為 initleoc() 。這初始化了一個由陰影類使用的隱藏輔助類。

    你可以將步驟 2 中的 C 代碼鏈接到 .exe 文件的原因是調(diào)用初始化函數(shù)等同于將模塊導(dǎo)入 Python ! (這是第二個關(guān)鍵的未記載事實。)

  4. 簡而言之,你可以用以下代碼使用擴展模塊初始化 Python 解釋器。

    #include <Python.h>
    ...
    Py_Initialize();  // Initialize Python.
    initmyAppc();  // Initialize (import) the helper class.
    PyRun_SimpleString("import myApp");  // Import the shadow class.
    
  5. Python C API 存在兩個問題,如果你使用除 MSVC 之外的編譯器用于構(gòu)建 python.dll ,這將會變得明顯。

    問題1:采用 FILE* 參數(shù)的所謂“極高級”函數(shù)在多編譯器環(huán)境中不起作用,因為每個編譯器的FILE結(jié)構(gòu)體概念都不同。從實現(xiàn)的角度來看,這些是非常 _低_ 級的功能。

    問題2:在為 void 函數(shù)生成包裝器時,SWIG 會生成以下代碼:

    Py_INCREF(Py_None);
    _resultobj = Py_None;
    return _resultobj;
    

    Py_None 是一個宏,它擴展為對 pythonNN.dll 中名為 _Py_NoneStruct 的復(fù)雜數(shù)據(jù)結(jié)構(gòu)的引用。同樣,此代碼將在多編譯器環(huán)境中失敗。將此類代碼替換為:

    return Py_BuildValue("");
    

    有可能使用 SWIG 的 %typemap 命令自動進(jìn)行更改,但我無法使其工作(我是一個完全的SWIG新手)。

  6. 使用 Python shell 腳本從 Windows 應(yīng)用程序內(nèi)部建立 Python 解釋器窗口并不是一個好主意;生成的窗口將獨立于應(yīng)用程序的窗口系統(tǒng)。相反,你(或 wxPythonWindow 類)應(yīng)該創(chuàng)建一個“本機”解釋器窗口。將該窗口連接到Python解釋器很容易。你可以將 Python的 i/o 重定向到支持讀寫的 _任意_ 對象,因此你只需要一個包含 read() 和 write() 方法的 Python 對象(在擴展模塊中定義)。

如何讓編輯器不要在我的 Python 源代碼中插入 tab ??

本 FAQ 不建議使用制表符, Python 樣式指南 PEP 8 ,為發(fā)行的 Python 代碼推薦 4 個空格;這也是 Emacs python-mode 默認(rèn)值。

在任何編輯器下,混合制表符和空格都是一個壞主意。 MSVC 在這方面沒有什么不同,并且很容易配置為使用空格: 點擊 Tools ? Options ? Tabs,對于文件類型“Default”,設(shè)置“Tab size”和“Indent size”為 4 ,并選擇“插入空格”單選按鈕。

如果混合制表符和空格導(dǎo)致前導(dǎo)空格出現(xiàn)問題, Python 會引發(fā) IndentationErrorTabError 。你還可以運行 tabnanny 模塊以批處理模式檢查目錄樹。

如何在不阻塞的情況下檢查按鍵??

使用 msvcrt 模塊。 這是一個標(biāo)準(zhǔn)的 Windows 專屬擴展模塊。 它定義了一個函數(shù) kbhit() 用于檢查是否有鍵盤中的某個鍵被按下,以及 getch() 用于獲取一個字符而不將其回顯。