找回密码
 加入
搜索
查看: 28|回复: 1

在Autoit中使用python

[复制链接]
发表于 11 小时前 | 显示全部楼层 |阅读模式
这两天无意间看到python有c api,之前孤陋寡闻了,然后就用本机已安装的环境调用测试了下确实可以哟
Local $pythonDll = DllOpen("C:\Users\subtlelonging\AppData\Local\Programs\Python\Python312\python312.dll")
DllCall($pythonDll, "none", "Py_Initialize")

DllCall($pythonDll, "int", "PyRun_SimpleString", "str", "def add(a, b): return a + b")

Local $pFunc = DllCall($pythonDll, "ptr", "PyObject_GetAttrString", "ptr", DllCall($pythonDll, "ptr", "PyImport_AddModule", "str", "__main__")[0], "str", "add")[0]

Local $pArgs = DllCall($pythonDll, "ptr", "PyTuple_New", "int", 2)[0]
DllCall($pythonDll, "none", "PyTuple_SetItem", "ptr", $pArgs, "int", 0, "ptr", DllCall($pythonDll, "ptr", "PyLong_FromLong", "long", 5)[0])
DllCall($pythonDll, "none", "PyTuple_SetItem", "ptr", $pArgs, "int", 1, "ptr", DllCall($pythonDll, "ptr", "PyLong_FromLong", "long", 7)[0])

Local $result = DllCall($pythonDll, "long", "PyLong_AsLong", "ptr", DllCall($pythonDll, "ptr", "PyObject_CallObject", "ptr", $pFunc, "ptr", $pArgs)[0])[0]
MsgBox(0, "Python计算结果", "5 + 7 = " & $result)

DllCall($pythonDll, "none", "Py_Finalize")
DllClose($pythonDll)
又翻了下资料发现python还有个嵌入版专门来解决没有python环境下的使用,虽然从官网下载过几次python但都没注意过这个嵌入版
下面就从下载开始使用嵌入版python,然后使用http库requests来请求演示网站,show下requests还有4个依赖库也需要下载
Global Const $URLS[6] = ["https://mirrors.huaweicloud.com/python/3.12.10/python-3.12.10-embeddable-amd64.zip", _
    "https://mirrors.huaweicloud.com/artifactory/pypi-public/packages/f9/9b/335f9764261e915ed497fcdeb11df5dfd6f7bf257d4a6a2a686d80da4d54/requests-2.32.3-py3-none-any.whl", _
    "https://mirrors.huaweicloud.com/artifactory/pypi-public/packages/6b/11/cc635220681e93a0183390e26485430ca2c7b5f9d33b15c74c2861cb8091/urllib3-2.4.0-py3-none-any.whl", _
    "https://mirrors.huaweicloud.com/artifactory/pypi-public/packages/6d/15/61933d1999bc5ad8cad612d67f02fa5b16a423076ea0816e39c2e797af12/idna-3.9-py3-none-any.whl", _
    "https://mirrors.huaweicloud.com/artifactory/pypi-public/packages/4a/7e/3db2bd1b1f9e95f7cddca6d6e75e2f2bd9f51b1246e546d88addca0106bd/certifi-2025.4.26-py3-none-any.whl", _
    "https://mirrors.huaweicloud.com/artifactory/pypi-public/packages/20/94/c5790835a017658cbfabd07f3bfb549140c3ac458cfc196323996b10095a/charset_normalizer-3.4.2-py3-none-any.whl"]

Global $g_sPythonDir = @TempDir & "\AutoitPy\Python-3.12.10"
Global $g_sSitePkgs = $g_sPythonDir & "\Lib\site-packages"
Global $g_sPythonDll = $g_sPythonDir & "\python312.dll"

If Not SetupPythonEnvironment() Then Exit MsgBox(0x10, "失败", "Python环境配置失败")

If Not FileExists($g_sPythonDll) Then Exit MsgBox(0x10, "错误", "未找到Python DLL: " & $g_sPythonDll)

Local $hDll = DllOpen($g_sPythonDll)
If $hDll = -1 Then Exit MsgBox(0x10, "错误", "无法加载Python DLL")

DllCall($hDll, "none:cdecl", "Py_SetPythonHome", "wstr", $g_sPythonDir)
DllCall($hDll, "none:cdecl", "Py_InitializeEx", "int", 0)
    
Local $pRequestsModule = PyImportModule($hDll, "requests")
If @error Then Exit Cleanup($hDll, "无法导入requests模块")
    
ExecuteRequestExample($hDll, $pRequestsModule, "get", "https://httpbin.org/get", 0, "基本GET请求")
ExecuteRequestExample($hDll, $pRequestsModule, "get", "https://httpbin.org/get", CreateParams($hDll), "带参数的GET请求")
ExecuteRequestExample($hDll, $pRequestsModule, "post", "https://httpbin.org/post", CreatePostData($hDll), "POST请求")
ExecuteRequestExample($hDll, $pRequestsModule, "get", "https://httpbin.org/headers", CreateHeaders($hDll), "带请求头的请求")
Cleanup($hDll)

Func SetupPythonEnvironment()
    DirCreate($g_sSitePkgs)
    
    If Not FileExists($g_sPythonDll) Then
        ConsoleWrite("+ 安装Python核心" & @CRLF)
        If Not _DownloadExtract($URLS[0], $g_sPythonDir) Then Return False
    EndIf
    
    Local $libs[5] = ["requests", "urllib3", "idna", "certifi", "charset_normalizer"]
    For $i = 0 To 4
        If Not FileExists($g_sSitePkgs & "" & $libs[$i] & "\__init__.py") Then
            ConsoleWrite("+ 安装依赖库: " & $libs[$i] & @CRLF)
            If Not _DownloadExtract($URLS[$i+1], $g_sSitePkgs) Then Return False
        EndIf
    Next
    Return FileExists($g_sPythonDir & "\python.exe")
EndFunc

Func _DownloadExtract($url, $target)
    Local $file = StringRegExpReplace($url, ".*/", "")
    Local $temp = @TempDir & "" & $file
    ConsoleWrite("+ 下载: " & $file & @CRLF)
    InetGet($url, $temp, 1)
    
    If Not FileExists($temp) Or FileGetSize($temp) < 1024 Then
        ConsoleWrite("! 下载失败" & @CRLF)
        Return False
    EndIf
    
    ConsoleWrite("+ 解压到: " & $target & @CRLF)
    Local $result = RunWait(@ComSpec & ' /c tar -xf "' & $temp & '" -C "' & $target & '"', "", @SW_HIDE)
    
    FileDelete($temp)
    Return $result = 0
EndFunc

Func PyImportModule($hDll, $moduleName)
    Local $pModule = DllCall($hDll, "ptr:cdecl", "PyImport_ImportModule", "str", $moduleName)
    If @error Or Not $pModule[0] Then Return SetError(1, 0, 0)
    Return $pModule[0]
EndFunc

Func PyObjectGetAttr($hDll, $pObject, $attrName)
    Local $pAttr = DllCall($hDll, "ptr:cdecl", "PyObject_GetAttrString", "ptr", $pObject, "str", $attrName)
    If @error Or Not $pAttr[0] Then Return SetError(1, 0, 0)
    Return $pAttr[0]
EndFunc

Func PyCallFunction($hDll, $pFunction, $pArgs = 0, $pKwargs = 0)
    If $pKwargs == 0 Then
        Local $pResult = DllCall($hDll, "ptr:cdecl", "PyObject_CallObject", "ptr", $pFunction, "ptr", $pArgs)
    Else
        Local $pResult = DllCall($hDll, "ptr:cdecl", "PyObject_Call", "ptr", $pFunction, "ptr", $pArgs, "ptr", $pKwargs)
    EndIf
    
    If @error Or Not $pResult[0] Then Return SetError(1, 0, 0)
    Return $pResult[0]
EndFunc

Func PyCreateTuple($hDll, $size)
    Local $pTuple = DllCall($hDll, "ptr:cdecl", "PyTuple_New", "int", $size)
    If @error Or Not $pTuple[0] Then Return SetError(1, 0, 0)
    Return $pTuple[0]
EndFunc

Func PySetTupleItem($hDll, $pTuple, $index, $pItem)
    DllCall($hDll, "int:cdecl", "PyTuple_SetItem", "ptr", $pTuple, "int", $index, "ptr", $pItem)
    If @error Then Return SetError(1, 0, 0)
    Return 1
EndFunc

Func PyCreateString($hDll, $str)
    Local $pStr = DllCall($hDll, "ptr:cdecl", "PyUnicode_FromString", "str", $str)
    If @error Or Not $pStr[0] Then Return SetError(1, 0, 0)
    Return $pStr[0]
EndFunc

Func PyCreateDict($hDll)
    Local $pDict = DllCall($hDll, "ptr:cdecl", "PyDict_New")
    If @error Or Not $pDict[0] Then Return SetError(1, 0, 0)
    Return $pDict[0]
EndFunc

Func PyDictSetItem($hDll, $pDict, $key, $pValue)
    Local $pKey = PyCreateString($hDll, $key)
    If @error Then Return SetError(1, 0, 0)
    
    DllCall($hDll, "int:cdecl", "PyDict_SetItem", "ptr", $pDict, "ptr", $pKey, "ptr", $pValue)
    If @error Then Return SetError(1, 0, 0)
    
    Return 1
EndFunc

Func PyGetLong($hDll, $pObject)
    Local $value = DllCall($hDll, "int:cdecl", "PyLong_AsLong", "ptr", $pObject)
    If @error Then Return SetError(1, 0, 0)
    Return $value[0]
EndFunc

Func PyGetBytes($hDll, $pBytesObject)
    Local $size = DllCall($hDll, "int:cdecl", "PyBytes_Size", "ptr", $pBytesObject)
    If @error Then Return SetError(1, 0, Binary(""))
    $size = $size[0]
    
    Local $pData = DllCall($hDll, "ptr:cdecl", "PyBytes_AsString", "ptr", $pBytesObject)
    If @error Or Not $pData[0] Then Return SetError(1, 0, Binary(""))
    
    Local $struct = DllStructCreate("byte[" & $size & "]")
    DllCall("kernel32.dll", "bool", "RtlMoveMemory", "struct*", $struct, "ptr", $pData[0], "ulong_ptr", $size)
    
    Return DllStructGetData($struct, 1)
EndFunc

Func CreateParams($hDll)
    Local $pParams = PyCreateDict($hDll)
    PyDictSetItem($hDll, $pParams, "param1", PyCreateString($hDll, "value1"))
    PyDictSetItem($hDll, $pParams, "param2", PyCreateString($hDll, "value2"))
    
    Local $pKwargs = PyCreateDict($hDll)
    PyDictSetItem($hDll, $pKwargs, "params", $pParams)
    
    Return $pKwargs
EndFunc

Func CreatePostData($hDll)
    Local $pData = PyCreateDict($hDll)
    PyDictSetItem($hDll, $pData, "username", PyCreateString($hDll, "autoit_user"))
    PyDictSetItem($hDll, $pData, "password", PyCreateString($hDll, "autoit_password"))
    
    Local $pKwargs = PyCreateDict($hDll)
    PyDictSetItem($hDll, $pKwargs, "data", $pData)
    
    Return $pKwargs
EndFunc

Func CreateHeaders($hDll)
    Local $pHeaders = PyCreateDict($hDll)
    PyDictSetItem($hDll, $pHeaders, "User-Agent", PyCreateString($hDll, "AutoItScript/1.0"))
    PyDictSetItem($hDll, $pHeaders, "Authorization", PyCreateString($hDll, "Bearer token123"))
    PyDictSetItem($hDll, $pHeaders, "X-Custom-Header", PyCreateString($hDll, "CustomValue"))
    
    Local $pKwargs = PyCreateDict($hDll)
    PyDictSetItem($hDll, $pKwargs, "headers", $pHeaders)
    
    Return $pKwargs
EndFunc

Func ExecuteRequestExample($hDll, $pRequestsModule, $funcName, $url, $pKwargs, $title)
    Local $pFunc = PyObjectGetAttr($hDll, $pRequestsModule, $funcName)
    If @error Then Return SetError(1, 0, 0)
    
    Local $pUrl = PyCreateString($hDll, $url)
    If @error Then Return SetError(1, 0, 0)
    
    Local $pArgs = PyCreateTuple($hDll, 1)
    If @error Then Return SetError(1, 0, 0)
    PySetTupleItem($hDll, $pArgs, 0, $pUrl)

    Local $pResponse = PyCallFunction($hDll, $pFunc, $pArgs, $pKwargs)
    If @error Then Return SetError(1, 0, 0)
    
    ProcessResponse($hDll, $pResponse, $title)
    Return 1
EndFunc

Func ProcessResponse($hDll, $pResponse, $title)
    Local $pStatusCode = PyObjectGetAttr($hDll, $pResponse, "status_code")
    Local $statusCode = PyGetLong($hDll, $pStatusCode)
    
    Local $pContent = PyObjectGetAttr($hDll, $pResponse, "content")
    Local $rawData = PyGetBytes($hDll, $pContent)
    Local $text = BinaryToString($rawData, 4)
    
    Local $displayText = StringLeft($text, 2500)
    If StringLen($text) > 2500 Then $displayText &= "..."
    
    MsgBox(0, $title, "状态码: " & $statusCode & @CRLF & @CRLF & "内容: " & $displayText)
EndFunc

Func Cleanup($hDll, $errorMsg = "")
    If $hDll <> -1 Then
        DllCall($hDll, "none:cdecl", "Py_Finalize")
        DllClose($hDll)
    EndIf
    
    If $errorMsg <> "" Then
        MsgBox(0x10, "错误", $errorMsg)
    EndIf
EndFunc
这个嵌入版挺好的,只需要10M的环境就能跑pytnon,无论是跟程序打包还是在线下载都挺方便的,肯定还有跟多好玩法还没探索



本帖子中包含更多资源

您需要 登录 才可以下载或查看,没有账号?加入

×

评分

参与人数 1金钱 +10 收起 理由
holley + 10 感谢分享

查看全部评分

发表于 3 小时前 | 显示全部楼层
这个厉害,希望有更多的资料
您需要登录后才可以回帖 登录 | 加入

本版积分规则

QQ|手机版|小黑屋|AUTOIT CN ( 鲁ICP备19019924号-1 )谷歌 百度

GMT+8, 2025-6-7 12:33 , Processed in 0.074302 second(s), 21 queries .

Powered by Discuz! X3.5 Licensed

© 2001-2025 Discuz! Team.

快速回复 返回顶部 返回列表