轉: http://www.cnblogs.com/cbscan/archive/2012/02/26/2368875.html
這個問題困擾我許久,終於解決了。
首先,在python解譯器中直接import wx,是沒有問題的,能夠正常使用wxPython,說明安裝wxPython成功了的。
但是,開啟gvim,編輯一個.py檔案,在指令碼中import wx,聲明一個變數app = wx.App(),再鍵入app.,結果沒有彈出自動補全菜單。
要知道,物件導向gui庫十分龐大,不太可能去記類的方法,因此,自動補全所提供的列表,非常重要。
gvim對python的自動補全支援在檔案pythoncomplete.vim中實現,瀏覽一下知道,補全功能依賴於動態語言的反射(eval、dir),如果該功能有問題的話,調用python函數showdbg就可以調查。
好,在gvim的命令欄鍵入:
:py showdbg()
從其中的資訊可以得知,gvim內建的python解譯器在import wx時失敗了。
再在gvim中測試一下:
:py import wx
提示import _core_時找不到模組。
用ollydbg附加到gvim中,發現python用LoadLibraryEx(參數LOAD_WITH_ALTERED_SEARCH_PATH)載入_core_.pyd,結果失敗了,Win32錯誤碼為ERROR_MOD_NOT_FOUND。自己寫一個C++測試程式(使用的vc版本應該和編譯wxPython的vc版本相同),用同樣的參數調用LoadLibraryEx,卻能成功。
總之,到這裡,確認gvim不能自動補全的原因是gvim內建的python解譯器import wx失敗,而後者import wx失敗又是因為windows在用LoadLibraryEx載入_core_.pyd時失敗。
觀察_core_.pyd這個動態庫的依賴項,主要缺失項是msvcr90.dll、msvcp90.dll(我用的vc2008編譯wxPython)。拷貝這兩個檔案到_core_.pyd所在目錄,再在gvim的命令列中鍵入:py import wx,仍然報錯,不過這次是彈出windows訊息框,說“An application has made an attempt to load the C runtime library without using a manifest”。
開啟_core_.pyd這個檔案,搜尋索引鍵“manifest”,看到內嵌的manifest,發現僅依賴於“Microsoft.Windows.Common-Controls”,對比編譯wxPython時產生的其他manifest檔案知道,還少了“Microsoft.VC90.CRT”項,從我的wxPython的lib\vc_dll目錄中隨便拷貝一個manifest檔案(如wxmsw28uh_adv_vc.dll.manifest),用mt工具嵌入_core_.pyd中即可:
mt -nologo -manifest wxmsw28uh_adv_vc.dll.manifest -outputresource:_core_.pyd;2
再一測試發現,所有的pyd檔案的內嵌manifest都有問題,用上面的命令依次更新每個pyd檔案即可。
總結一下,我在windows下用gvim編寫python代碼,訪問wxPython庫時gvim內建的自動補全失效,原因是用wxPython 2.8.12.1官方內建的編譯指令碼輸出的*.pyd檔案都被嵌入了錯誤的manifest,修複方法是,找一個編譯wxPython時產生的完整的manifest依次嵌入所有的*.pyd檔案。
作為參考,我所嵌入的manifest檔案內容(當然和我所使用的vc版本有關):
<?xml version='1.0' encoding='UTF-8' standalone='yes'?><assembly xmlns='urn:schemas-microsoft-com:asm.v1' manifestVersion='1.0'> <trustInfo xmlns="urn:schemas-microsoft-com:asm.v3"> <security> <requestedPrivileges> <requestedExecutionLevel level='asInvoker' uiAccess='false' /> </requestedPrivileges> </security> </trustInfo> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.VC90.CRT' version='9.0.21022.8' processorArchitecture='x86' publicKeyToken='1fc8b3b9a1e18e3b' /> </dependentAssembly> </dependency> <dependency> <dependentAssembly> <assemblyIdentity type='win32' name='Microsoft.Windows.Common-Controls' version='6.0.0.0' processorArchitecture='x86' publicKeyToken='6595b64144ccf1df' language='*' /> </dependentAssembly> </dependency></assembly>
複製代碼
另外,之所以python解譯器和其他python容器程式能夠成功import wx,是因為他們在import wx之前已經載入好了正確版本的crt(比如python解譯器本身就是vc2008編譯的) ,而gvim是c語言編寫的,在import wx->import _core_的時候才第一次載入c++庫,此時殘缺的內嵌manifest會導致錯誤。
雖然是wxPython的bug,但還是得說微軟2。