有人向我反應,在代碼裏同時用個人python模塊uiautomation和其它另外一個模塊後,腳本運行時會報錯,但單獨使用任意一個模塊時都是正常的,沒有錯誤。issue連接python
我用一個例子來演示下這個問題是如何出現的。git
假設我須要寫一個module,這個module須要提供獲取當前鼠標光標下窗口句柄的功能,這須要調用系統C API來實現。github
實現以下:函數
module1.pyui
#!python3 # -*- coding: utf-8 -*- import ctypes import ctypes.wintypes class POINT(ctypes.Structure): _fields_ = [("x", ctypes.wintypes.LONG), ("y", ctypes.wintypes.LONG)] ctypes.windll.user32.WindowFromPoint.argtypes = (POINT, ) ctypes.windll.user32.WindowFromPoint.restype = ctypes.c_void_p ctypes.windll.user32.GetCursorPos.argtypes = (ctypes.POINTER(POINT), ) def WindowFromPoint(x, y): return ctypes.windll.user32.WindowFromPoint(POINT(x, y)) def GetCursorPos(): point = POINT(0, 0) ctypes.windll.user32.GetCursorPos(ctypes.byref(point)) return point.x, point.y def WindowFromCursor(): x, y = GetCursorPos() return WindowFromPoint(x, y)
調用的代碼以下spa
test.py指針
#!python3 # -*- coding:utf-8 -*- import module1 def main(): print('the handle under cursor is', module1.WindowFromCursor()) if __name__ == '__main__': main()
運行結果以下rest
the handle under cursor is 1839250
這時複製一份module1.py,重命名爲module2.py,他們的代碼是徹底同樣的code
在test.py同時調用這兩個module,代碼以下blog
#!python3 # -*- coding:utf-8 -*- import module1 import module2 def main(): print('the handle under cursor is', module1.WindowFromCursor()) print('the handle under cursor is', module2.WindowFromCursor()) if __name__ == '__main__': main()
運行就會報錯了
ctypes.ArgumentError: argument 1: <class 'TypeError'>: expected LP_POINT instance instead of pointer to POINT
但分開單獨調用任一個模塊就是正常的,不會出錯。
這是由於,module1,module2調用的同一個C函數,在設置argtypes的時候,後面的修改會覆蓋前面的設置。
執行
import module1 import module2
後,C函數中的POINT參數必須是module2.POINT纔是合法的。
在用module1調用時,傳入的參數類型是module1.POINT,運行時就會報錯了。
這種錯誤應該只有在參數中有結構體或結構體指針時纔會出現。
假設module1, module2分別是兩我的寫,而這兩個module都會調用同一個C函數,C函數參數裏有你自定義的ctypes.Structure類型,你又要同時用這兩個module,只要有一個module設置了argtypes,運行時可能就會出錯。
解決方法是,在module1, module2中註釋兩行代碼
#ctypes.windll.user32.WindowFromPoint.argtypes = (POINT, ) ctypes.windll.user32.WindowFromPoint.restype = ctypes.c_void_p #ctypes.windll.user32.GetCursorPos.argtypes = (ctypes.POINTER(POINT), )
不要修改argtypes,再運行test.py就不會報錯了。