【问题标题】:Call python function with arguments and get returned value in autohotkey使用参数调用python函数并在autohotkey中获取返回值
【发布时间】:2020-02-24 05:52:16
【问题描述】:

我有一个名为“server.py”的python 脚本,在其中我有一个函数def calcFunction(arg1): ... return output 如何使用参数调用函数calcFunction 并在autohotkey 中使用返回值?这就是我想在 autohotkey 中做的事情:

ToSend = someString ; a string
output = Run server.py, calcFunction(ToSend) ; get the returned value from the function with ToSend as argument
Send, output ; use the returned value in autohotkey

我在网上看过,但似乎没有什么能完全回答我的问题。还能做到吗?

【问题讨论】:

  • 我认为您可能需要将 Python 脚本 print() 作为输出。
  • 如果您感兴趣,我已经通过将结果写入 TXT 文件解决了类似的问题。
  • 你可以在python函数中使用StdOut吗?然后在 wscript shell 中运行 python 脚本,将 StdOut 值返回给 ahk 。 . .十分简单。也无需写入文件或剪贴板。

标签: python autohotkey


【解决方案1】:

为了将参数发送到 Python,您可以使用 Python 脚本中的参数。您可以使用 sys 库来做到这一点:

import sys
print(sys.argv[0]) # name of file
print(sys.argv[1]) # first argument
print(sys.argv[2]) # second argument...

在您的 AutoHotKey 脚本中,您可以通过在指定文件名后立即将参数添加为参数来将参数发送到 Python 脚本:

RunWait, server.py "This will be printed as the first argument!" "This is the second!"

然后,要将函数的输出返回给 AHK,您可以通过利用 exit() 函数再次使用 sys

sys.exit(EXIT_NUMBER)

回到 AHK,你会在变量 ErrorLevel 中收到 EXIT_NUMBER。 综上所述,您的代码应如下所示:

; AHK
RunWait, server.py "%ToSend%"

# Python
sys.exit(calcFunction(sys.argv[1]))

; AHK
MsgBox %ErrorLevel%

【讨论】:

  • 获取错误码(python 的 EXIT_NUMBER)与获取 server.py 函数在“ToSend”上运行的结果并不完全相同。
  • 没错,另一种方法是让 python 将返回值转储到一个文件中,当程序退出时,AHK 可以读取该文件。在我的回答中,我假设 return 语句是一个整数,我猜这使它部分无效。
【解决方案2】:

使用python COM服务器,ahk可以真正调用python函数。直接。
你可以这样使用它:MsgBox % pythonComServer.toUppercase("hello world")

简单示例:返回大写字符串
使用来自 How to program hotstrings in python like in autohotkey 的 python 部分并将其用于 ahk 部分:

调用python函数uppercase.ahk

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
SetBatchLines, -1
#KeyHistory 0
ListLines Off

pythonComServer:=ComObjCreate("Python.stringUppercaser")
;or
; pythonComServer:=ComObjCreate("{C70F3BF7-2947-4F87-B31E-9F5B8B13D24F}") ;use your own CLSID

MsgBox % pythonComServer.toUppercase("hello world")
Exitapp

f3::Exitapp

定制版:(数学)使用SymPy简化表达式
首先阅读此内容以了解:How to program hotstrings in python like in autohotkey

sympy com server.py

from sympy import simplify, Number, N
from sympy.parsing.sympy_parser import standard_transformations, implicit_multiplication_application, convert_xor
from sympy.parsing.sympy_parser import parse_expr

from decimal import Decimal

from winsound import MessageBeep

transformations = standard_transformations + (implicit_multiplication_application, convert_xor)

def removeTrailingZerosFromNum(num):
    dec = Decimal(str(num))

    tup = dec.as_tuple()
    delta = len(tup.digits) + tup.exponent
    digits = ''.join(str(d) for d in tup.digits)
    if delta <= 0:
        zeros = abs(tup.exponent) - len(tup.digits)
        val = '0.' + ('0' * zeros) + digits
    else:
        val = digits[:delta] + ('0' * tup.exponent) + '.' + digits[delta:]
    val = val.rstrip('0')
    if val[-1] == '.':
        val = val[:-1]
    if tup.sign:
        return '-' + val
    return val


def removeTrailingZerosFromExpr(operatorObject):
    if operatorObject.args:
        return type(operatorObject)(*[removeTrailingZerosFromExpr(i) for i in operatorObject.args])
    else:
        try:
            return Number(removeTrailingZerosFromNum(operatorObject))
        except:
            return operatorObject

def removeTrailingZerosFromExprOrNumber(operatorObject):
    try:
        return removeTrailingZerosFromNum(operatorObject)
    except:
        return removeTrailingZerosFromExpr(operatorObject)

class BasicServer:
    # list of all method names exposed to COM
    _public_methods_ = ["parExprN"]

    @staticmethod
    def parExprN(clipBak):
        parsed = parse_expr(clipBak, transformations=transformations)
        simplified = simplify(N(parsed))
        finalStr = str(removeTrailingZerosFromExprOrNumber(simplified))
        MessageBeep(-1)
        return finalStr.replace("**", "^")

if __name__ == "__main__":
    import sys

    if len(sys.argv) < 2:
        print("Error: need to supply arg (""--register"" or ""--unregister"")")
        sys.exit(1)
    else:
        import win32com.server.register
        import win32com.server.exception

        # this server's CLSID
        # NEVER copy the following ID 
        # Use "print(pythoncom.CreateGuid())" to make a new one.
        myClsid="{4530C817-6C66-46C8-8FB0-E606970A8DF6}"
        # this server's (user-friendly) program ID, can be anything you want
        myProgID="Python.SimplifyExpr"
        
        import ctypes
        def make_sure_is_admin():
            try:
                if ctypes.windll.shell32.IsUserAnAdmin():
                    return
            except:
                pass
            exit("YOU MUST RUN THIS AS ADMIN")

        if sys.argv[1] == "--register":
            make_sure_is_admin()

            import pythoncom
            import os.path
            realPath = os.path.realpath(__file__)
            dirName = os.path.dirname(realPath)
            nameOfThisFile = os.path.basename(realPath)
            nameNoExt = os.path.splitext(nameOfThisFile)[0]
            # stuff will be written here
            # HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\${myClsid}
            # HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{c2467d33-71c5-4057-977c-e847c2286882}
            # and here
            # HKEY_LOCAL_MACHINE\SOFTWARE\Classes\${myProgID}
            # HKEY_LOCAL_MACHINE\SOFTWARE\Classes\Python.SimplifyExpr
            win32com.server.register.RegisterServer(
                clsid=myClsid,
                # I guess this is {fileNameNoExt}.{className}
                pythonInstString=nameNoExt + ".BasicServer", #sympy com server.BasicServer
                progID=myProgID,
                # optional description
                desc="(math) SymPy simplify Expression",
                #we only want the registry key LocalServer32
                #we DO NOT WANT InProcServer32: pythoncom39.dll, NO NO NO
                clsctx=pythoncom.CLSCTX_LOCAL_SERVER,
                #this is needed if this file isn't in PYTHONPATH: it tells regedit which directory this file is located
                #this will write HKEY_LOCAL_MACHINE\SOFTWARE\Classes\CLSID\{4530C817-6C66-46C8-8FB0-E606970A8DF6}\PythonCOMPath : dirName
                addnPath=dirName,
            )
            print("Registered COM server.")
            # don't use UseCommandLine(), as it will write InProcServer32: pythoncom39.dll
            # win32com.server.register.UseCommandLine(BasicServer)
        elif sys.argv[1] == "--unregister":
            make_sure_is_admin()

            print("Starting to unregister...")

            win32com.server.register.UnregisterServer(myClsid, myProgID)

            print("Unregistered COM server.")
        else:
            print("Error: arg not recognized")

注册:
python "sympy com server.py" --register


sympy com client.ahk

#NoEnv ; Recommended for performance and compatibility with future AutoHotkey releases.
#SingleInstance, force
SendMode Input ; Recommended for new scripts due to its superior speed and reliability.
SetWorkingDir %A_ScriptDir% ; Ensures a consistent starting directory.
SetBatchLines, -1
#KeyHistory 0
ListLines Off

sympyComServer:=ComObjCreate("Python.SimplifyExpr")
;or
; pythonComServer:=ComObjCreate("{4530C817-6C66-46C8-8FB0-E606970A8DF6}") ;use your own CLSID

; clipboard:=sympyComServer.parExprN("1+3*7")
clipboard:=sympyComServer.parExprN("1/3 + 1/2")

$#s::
clipboard:=sympyComServer.parExprN(clipboard)
return

f3::Exitapp

【讨论】:

    猜你喜欢
    • 2013-10-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2017-12-14
    • 1970-01-01
    • 1970-01-01
    • 2016-08-15
    • 2020-01-29
    相关资源
    最近更新 更多