【问题标题】:How do I embed an AppleScript in a Python script?如何在 Python 脚本中嵌入 AppleScript?
【发布时间】:2020-12-31 08:48:30
【问题描述】:

我正在尝试在 Python 脚本中嵌入 AppleScript。我不想将 AppleScript 保存为文件,然后将其加载到我的 Python 脚本中。有没有办法在 Python 中将 AppleScript 作为字符串输入并让 Python 执行 AppleScript?非常感谢。

这是我的脚本: 导入子流程 重新进口 导入操作系统

def get_window_title():
    cmd = """osascript<<END
    tell application "System Events"
        set frontApp to name of first application process whose frontmost is true
    end tell
    tell application frontApp
        if the (count of windows) is not 0 then
            set window_name to name of front window
        end if
    end tell
    return window_name
    END"""

    p = subprocess.Popen(cmd, shell=True)
    p.terminate()
    return p

def get_class_name(input_str):
    re_expression = re.compile(r"(\w+)\.java")
    full_match = re_expression.search(input_str)
    class_name = full_match.group(1)
    return class_name

print get_window_title()

【问题讨论】:

标签: python macos applescript


【解决方案1】:

使用subprocess:

from subprocess import Popen, PIPE

scpt = '''
    on run {x, y}
        return x + y
    end run'''
args = ['2', '2']

p = Popen(['osascript', '-'] + args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate(scpt)
print (p.returncode, stdout, stderr)

【讨论】:

  • 在 python 3 中这不起作用,需要在 popen 上添加一个额外的参数 universal_newlines=True。请参阅下面的示例stackoverflow.com/a/45133926/1534775
  • @gbonetti 这不一定是真的。在 python 3 中,如果您的脚本文本包含非 ascii 字符,这实际上会引入更多错误。您可能需要关闭 universal_newlines 并根据需要对脚本进行编码。前任。 stdout, stderr = p.communicate(scpt.encode('utf-8')),然后是stdout.decode('utf-8')
【解决方案2】:

this article 中的示例 3 建议:

#!/usr/bin/env python
#sleepy-mac.py
#makes my mac very sleepy

import os
cmd = """osascript -e 'tell app "Finder" to sleep'"""
def stupidtrick():
     os.system(cmd)
stupidtrick()

然而,如今,subsystem.Popen 通常比os.system 更受欢迎(这篇文章是三年前的,当时没有人看到os.system 的电话会尖叫;-)。

【讨论】:

  • 我之前看过那个链接,但我的脚本无法正常工作。我编辑了我的问题以包含我要执行的脚本。我认为错误是我无法从 AppleScript 检索返回值。我查看了 Popen 对象,但找不到任何可以对返回值进行操作的内容。
【解决方案3】:

在 python 3 中会略有不同:

script = 'tell "some application" to do something'
p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE, universal_newlines=True)
stdout, stderr = p.communicate(script)

Popen 现在需要一个类似字节的对象,要传递一个字符串,需要 universal_newlines=True 参数。

【讨论】:

  • 在 python 3 中,如果脚本包含非 ascii 字符,这将失败。更好的方法是执行universal_newlines=False,然后根据需要对script 进行编码并解码stdout
【解决方案4】:

这是一个简单的 python3 同步示例,如果您希望您的 python 代码不等待 Applescript 完成。在本例中,两个say 命令并行执行。

from subprocess import Popen

def exec_applescript(script):
    p = Popen(['osascript', '-e', script])

exec_applescript('say "I am singing la la la la" using "Alex" speaking rate 140 pitch 60')
exec_applescript('say "Still singing, hahaha" using "Alex" speaking rate 140 pitch 66')

【讨论】:

    【解决方案5】:

    https://pypi.org/project/applescript/

    import applescript
    resp = applescript.tell.app("System Events",'''
    set frontApp to name of first application process whose frontmost is true
    return "Done"
    ''')
    assert resp.code == 0, resp.err
    print(resp.out)
    

    等等。 大多数建议,包括我引用的“applescript”,都缺少 osascript 的一项重要设置——将 -s 选项设置为“s”,否则您将难以解析输出。

    【讨论】:

      【解决方案6】:

      subprocess.run()now preferred 超过 subprocess.popen()。这是运行 AppleScript 代码并返回结果的一种非常简单的方法。

      import subprocess
      
      def get_window_title():
          cmd = """
              tell application "System Events"
                  set frontApp to name of first application process whose frontmost is true
              end tell
              tell application frontApp
                  if the (count of windows) is not 0 then
                      set window_name to name of front window
                  end if
              end tell
              return window_name
          """
          result = subprocess.run(['osascript', '-e', cmd], capture_output=True)
          return result.stdout
      
      print(get_window_title())
      

      【讨论】:

      • Python 3.6 需要从 subrpocess.run 中删除 , capture_output=True 部分才能使其正常工作
      【解决方案7】:

      我不会嵌入 AppleScript,而是使用 appscript。我从未使用过 Python 版本,但它在 Ruby 中非常好用。 And make sure that, if you're installing it on Snow Leopard, you have the latest version of XCode. 但是,到目前为止,我还无法在 Snow Leopard 上安装它。但我只吃雪豹约 1 天,所以你的里程可能会有所不同。

      【讨论】:

      • 很抱歉听到您遇到问题;它应该可以工作(在这里可以)。您是否尝试在 rb-appscript-discuss (rubyforge.org/mail/?group_id=2346) 上发帖寻求帮助?
      • 有:谢谢你的链接,但是我1.5天前才安装了雪豹,今天去旅游了;我还没有真正努力过。不过,如果我不能让它工作,我会检查一下;再次感谢。
      • 有:确实,我需要做的就是update XCode。不过再次感谢!
      • 很高兴你把它整理好了。是的,如果 OP 不介意第三方安装,那么 py-appscript 是一个更好的解决方案。例如这将获取最前面进程中所有窗口的名称:app('System Events').application_processes[its.frontmost==True].first.windows.name()
      【解决方案8】:

      你可以使用os.system:

      import os
      os.system('''
          osascript -e 
           '[{YOUR SCRIPT}]'
           '[{GOES HERE}]'
          ''')
      

      或者,正如 Alex Martelli 所建议的,您可以使用变量:

      import os
      script = '''
          [{YOUR SCRIPT}]
          [{GOES HERE}]
      '''
      os.system('osascript -e ' + script)
      

      【讨论】:

        【解决方案9】:

        这是python中的一个通用函数。只需传递带/不带 args 的 applescript 代码,然后将值作为字符串取回。感谢this的回答。

        from subprocess import Popen, PIPE
        
        def run_this_scpt(scpt, args=[]):
            p = Popen(['osascript', '-'] + args, stdin=PIPE, stdout=PIPE, stderr=PIPE)
            stdout, stderr = p.communicate(scpt)
            return stdout
        
        #Example of how to run it.
        run_this_scpt("""tell application "System Events" to keystroke "m" using {command down}""")
        
        #Example of how to run with args.
        run_this_scpt('''
            on run {x, y}
                return x + y
            end run''', ['2', '2'])
        

        【讨论】:

        • 如果在 Popen 参数末尾添加universal_newlines=True,Python 3.6 运行不会出错
        猜你喜欢
        • 1970-01-01
        • 2016-10-07
        • 1970-01-01
        • 2021-11-12
        • 1970-01-01
        • 1970-01-01
        • 2022-01-26
        • 2021-12-07
        相关资源
        最近更新 更多