Python在Windows上的常見(jiàn)問(wèn)題?

我怎樣在Windows下運行一個(gè)Python程序??

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

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:\>

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

D:\YourName\Projects\Python>

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

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

首先,確保命令窗口能夠將“py”識別為指令來(lái)開(kāi)啟解釋器。 如果你打開(kāi)過(guò)一個(gè)命令窗口, 嘗試輸入命令 py 然后按回車(chē):

C:\Users\YourName> py

然后你應當看見(jiàn)類(lèi)似類(lèi)似這樣的東西:

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)以“交互模式”打開(kāi)。這意味著(zhù)你可以交互輸入Python語(yǔ)句或表達式,并在等待時(shí)執行或評估它們。這是Python最強大的功能之一。輸入幾個(gè)表達式并看看結果:

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

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

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

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

C:\Users\YourName>

那么現在可以讓 py 命令執行你的腳本,只需要輸入 py 和腳本路徑:

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

我怎么讓 Python 腳本可執行??

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

為什么有時(shí)候 Python 程序會(huì )啟動(dòng)緩慢??

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

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

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

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

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

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

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

我怎樣將 Python 嵌入一個(gè) Windows 程序??

在 Windows 應用程序中嵌入 Python 解釋器可以總結如下:

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

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

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

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

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

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

  4. 簡(jiǎn)而言之,你可以用以下代碼使用擴展模塊初始化 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 存在兩個(gè)問(wèn)題,如果你使用除 MSVC 之外的編譯器用于構建 python.dll ,這將會(huì )變得明顯。

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

    問(wèn)題2:在為 void 函數生成包裝器時(shí),SWIG 會(huì )生成以下代碼:

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

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

    return Py_BuildValue("");
    

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

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

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

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

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

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

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

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