jjzjj

python - 在 Mac 上,如何为菜单栏(等)中显示脚本名称而不是 Python 的 python 脚本创建拖放应用程序?

coder 2023-08-24 原文

我有一个 Python 脚本,我想通过点击某个东西或拖放一个我想在那个东西上打开的文件来启动它。我还想避免烦人的 mac Python 问题,即解释器 (Python) 的名称而不是脚本的名称。我不想使用 py2app,因为我不想捆绑 Python 并希望 python 文件保留为文本文件。我想要一个纯 Python(或最好的 shell 脚本解决方案。)This展示了如何做所有事情,但拖放部分除外; this展示了如何通过创建一个包来实现同样的目的,它允许一个人控制图标。

最佳答案

我的问题有了答案,但我希望有人能想出不那么复杂的东西。我想出的解决方案是一个 Python 脚本来创建一个 AppleScript(呃!),将其编译成一个包,然后修改该包以更改允许的文件扩展名、图标等。

在没有 AppleScript(或使用 py2app)的情况下启动 wxpython 脚本时,我没有找到使拖放工作正常的方法,而且我无法让 AppleScript 在我创建的包中工作,我不得不使用osacompile 为我创建包。

我更喜欢这种方法 herehere ,其中一个人“手动”创建 plist 文件,而不是像我在这里所做的那样修改外部创建的文件,但下面的脚本确实完成了这项工作。

#!/usr/bin/env python
'''This script creates an AppleScript app to launch a python script.
The app is created in the current working directory. A softlink is
made to an app version of the current python (with name
.../Resources/Python.app/Contents/MacOS/Python and found in the
directory tree of calling python interpreter), but with the name of
the app to be created, this means that the app name shows up in the
Mac menus.

Run this script with one, two or three arguments:
    <python script>
    <project name>
    <icon file>
The python script path may be specified relative to the current path
or given an absolute path, but will be accessed via an absolute path
in the AppleScript.

If the project name is not specified, it will be taken from the root
name of the script.

If the icon file is not specified, it will be assumed to be the same
as the python script, but with the extension changed from .py to
.icns.  (Note that image files can be saved in ICNS format in
Preview.). No error occurs if the icon file does not exist.
'''
import sys, os, os.path, stat, shutil, subprocess, plistlib
allowedfiletypes = ['txt',]
allowedtypedesc = 'Text Files'
scripttype = 'Editor' # use 'Viewer' if the script does not change the file

def Usage():
    print("\n\tUsage: python "+sys.argv[0]+" <python script> [<project name>] [<icon file>]\n")
    sys.exit()

if not 2 <= len(sys.argv) <= 4:
    Usage()

script = os.path.abspath(sys.argv[1])
if not os.path.exists(script):
    print("\nFile "+script+" not found")
    Usage()
if os.path.splitext(script)[1].lower() != '.py':
    print("\nScript "+script+" does not have extension .py")
    Usage()
# make sure we found it
if not os.path.exists(script):
    print("\nFile "+script+" not found")
    Usage()

if len(sys.argv) >= 3:
    project = sys.argv[2]
else:
    project = os.path.splitext(os.path.split(script)[1])[0]

if len(sys.argv) == 4:
    iconfile = sys.argv[3]
else:
    iconfile = os.path.splitext(script)[0]+'.icns'

# app will be created in current working directory 
apppath = os.path.abspath(os.path.join('.',project+".app")) # full path to app bundle

# find the python application; which must be an OS X app
pythonpath,top = os.path.split(os.path.realpath(sys.executable))
while top:
    if 'Resources' in pythonpath:
        pass
    elif os.path.exists(os.path.join(pythonpath,'Resources')):
        break
    pythonpath,top = os.path.split(pythonpath)
else:
    print("\nSorry, failed to find a Resources directory associated with "+str(sys.executable))
    sys.exit()
pythonapp = os.path.join(pythonpath,'Resources','Python.app','Contents','MacOS','Python')
if not os.path.exists(pythonapp): 
    print("\nSorry, failed to find a Python app in "+str(pythonapp))
    sys.exit()

# new name to call python
newpython =  os.path.join(apppath,"Contents","MacOS",project)

if os.path.exists(apppath): # cleanup
    print("\nRemoving old "+project+" app ("+str(apppath)+")")
    shutil.rmtree(apppath)

# create an AppleScript that launches python with the requested app
shell = os.path.join("/tmp/","appscrpt.script")
f = open(shell, "w")
f.write('''(*   drag and drop AppleScript 
     It can launch a python script by double clicking or by dropping a data file
     over the app. It runs the script in a terminal window.
*)

(* test if a file is present and exit with an error message if it is not  *)
on TestFilePresent(appwithpath)
        tell application "System Events"
                if (file appwithpath exists) then
                else
                        display dialog "Error: file " & appwithpath & " not found. If you have moved this file, recreate the AppleScript." with icon caution buttons {{"Quit"}}
                        return
                end if
        end tell
end TestFilePresent

(* 
------------------------------------------------------------------------
this section responds to a double-click. No file is supplied 
------------------------------------------------------------------------ 
*)
on run
        set python to "{:s}"
        set appwithpath to "{:s}"
        TestFilePresent(appwithpath)
        TestFilePresent(python)
        tell application "Terminal"
                activate
                do script python & " " & appwithpath & "; exit"
        end tell
end run

(*
-----------------------------------------------------------------------------------------------
this section handles starting with files dragged into the AppleScript
 o it goes through the list of file(s) dragged in
 o then it converts the colon-delimited macintosh file location to a POSIX filename
 o for every non-directory file dragged into the icon, it starts GSAS-II, passing the file name
------------------------------------------------------------------------------------------------
*)

on open names
        set python to "{:s}"
        set appwithpath to "{:s}"
        TestFilePresent(appwithpath)
        repeat with filename in names
                set filestr to (filename as string)
                if filestr ends with ":" then
                        (* should not happen, skip directories *)
                else
                        (* if this is an input file, open it *)
                        set filename to the quoted form of the POSIX path of filename
                        tell application "Terminal"
                                activate
                                do script python & " " & appwithpath & " " & filename & "; exit"
                        end tell
                end if
        end repeat
end open
'''.format(newpython,script,newpython,script))
f.close()

try: 
    subprocess.check_output(["osacompile","-o",apppath,shell],stderr=subprocess.STDOUT)
except subprocess.CalledProcessError, msg:
    print('Error compiling AppleScript:')
    print msg.output
    sys.exit()

# create a link to the python app, but named to match the project
os.symlink(pythonapp,newpython)

# change the icon
oldicon = os.path.join(apppath,"Contents","Resources","droplet.icns")
if os.path.exists(iconfile) and os.path.exists(oldicon):
    shutil.copyfile(iconfile,oldicon)

# Edit the app plist file to restrict the type of files that can be dropped
d = plistlib.readPlist(os.path.join(apppath,"Contents",'Info.plist'))
d['CFBundleDocumentTypes'] = [{
    'CFBundleTypeExtensions': allowedfiletypes,
    'CFBundleTypeName': allowedtypedesc,
    'CFBundleTypeRole': scripttype}]
plistlib.writePlist(d,os.path.join(apppath,"Contents",'Info.plist'))

print("\nCreated "+project+" app ("+str(apppath)+
      ").\nViewing app in Finder so you can drag it to the dock if, you wish.")
subprocess.call(["open","-R",apppath])

有没有人有更好的方法在不使用 py2app 的情况下做到这一点?

关于python - 在 Mac 上,如何为菜单栏(等)中显示脚本名称而不是 Python 的 python 脚本创建拖放应用程序?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/17479802/

有关python - 在 Mac 上,如何为菜单栏(等)中显示脚本名称而不是 Python 的 python 脚本创建拖放应用程序?的更多相关文章

  1. ruby - 在 Ruby 程序执行时阻止 Windows 7 PC 进入休眠状态 - 2

    我需要在客户计算机上运行Ruby应用程序。通常需要几天才能完成(复制大备份文件)。问题是如果启用sleep,它会中断应用程序。否则,计算机将持续运行数周,直到我下次访问为止。有什么方法可以防止执行期间休眠并让Windows在执行后休眠吗?欢迎任何疯狂的想法;-) 最佳答案 Here建议使用SetThreadExecutionStateWinAPI函数,使应用程序能够通知系统它正在使用中,从而防止系统在应用程序运行时进入休眠状态或关闭显示。像这样的东西:require'Win32API'ES_AWAYMODE_REQUIRED=0x0

  2. python - 如何使用 Ruby 或 Python 创建一系列高音调和低音调的蜂鸣声? - 2

    关闭。这个问题是opinion-based.它目前不接受答案。想要改进这个问题?更新问题,以便editingthispost可以用事实和引用来回答它.关闭4年前。Improvethisquestion我想在固定时间创建一系列低音和高音调的哔哔声。例如:在150毫秒时发出高音调的蜂鸣声在151毫秒时发出低音调的蜂鸣声200毫秒时发出低音调的蜂鸣声250毫秒的高音调蜂鸣声有没有办法在Ruby或Python中做到这一点?我真的不在乎输出编码是什么(.wav、.mp3、.ogg等等),但我确实想创建一个输出文件。

  3. ruby - 如何将脚本文件的末尾读取为数据文件(Perl 或任何其他语言) - 2

    我正在寻找执行以下操作的正确语法(在Perl、Shell或Ruby中):#variabletoaccessthedatalinesappendedasafileEND_OF_SCRIPT_MARKERrawdatastartshereanditcontinues. 最佳答案 Perl用__DATA__做这个:#!/usr/bin/perlusestrict;usewarnings;while(){print;}__DATA__Texttoprintgoeshere 关于ruby-如何将脚

  4. ruby - 如何指定 Rack 处理程序 - 2

    Rackup通过Rack的默认处理程序成功运行任何Rack应用程序。例如:classRackAppdefcall(environment)['200',{'Content-Type'=>'text/html'},["Helloworld"]]endendrunRackApp.new但是当最后一行更改为使用Rack的内置CGI处理程序时,rackup给出“NoMethodErrorat/undefinedmethod`call'fornil:NilClass”:Rack::Handler::CGI.runRackApp.newRack的其他内置处理程序也提出了同样的反对意见。例如Rack

  5. ruby - 在 Ruby 中编写命令行实用程序 - 2

    我想用ruby​​编写一个小的命令行实用程序并将其作为gem分发。我知道安装后,Guard、Sass和Thor等某些gem可以从命令行自行运行。为了让gem像二进制文件一样可用,我需要在我的gemspec中指定什么。 最佳答案 Gem::Specification.newdo|s|...s.executable='name_of_executable'...endhttp://docs.rubygems.org/read/chapter/20 关于ruby-在Ruby中编写命令行实用程序

  6. ruby-on-rails - Rails 应用程序之间的通信 - 2

    我构建了两个需要相互通信和发送文件的Rails应用程序。例如,一个Rails应用程序会发送请求以查看其他应用程序数据库中的表。然后另一个应用程序将呈现该表的json并将其发回。我还希望一个应用程序将存储在其公共(public)目录中的文本文件发送到另一个应用程序的公共(public)目录。我从来没有做过这样的事情,所以我什至不知道从哪里开始。任何帮助,将不胜感激。谢谢! 最佳答案 无论Rails是什么,几乎所有Web应用程序都有您的要求,大多数现代Web应用程序都需要相互通信。但是有一个小小的理解需要你坚持下去,网站不应直接访问彼此

  7. ruby - 无法运行 Rails 2.x 应用程序 - 2

    我尝试运行2.x应用程序。我使用rvm并为此应用程序设置其他版本的ruby​​:$rvmuseree-1.8.7-head我尝试运行服务器,然后出现很多错误:$script/serverNOTE:Gem.source_indexisdeprecated,useSpecification.Itwillberemovedonorafter2011-11-01.Gem.source_indexcalledfrom/Users/serg/rails_projects_terminal/work_proj/spohelp/config/../vendor/rails/railties/lib/r

  8. ruby - 如何为 emacs 安装 ruby​​-mode - 2

    我刚刚为fedora安装了emacs。我想用emacs编写ruby。为ruby​​提供代码提示、代码完成类型功能所需的工具、扩展是什么? 最佳答案 ruby-mode已经包含在Emacs23之后的版本中。不过,它也可以通过ELPA获得。您可能感兴趣的其他一些事情是集成RVM、feature-mode(Cucumber)、rspec-mode、ruby-electric、inf-ruby、rinari(用于Rails)等。这是我当前用于Ruby开发的Emacs配置:https://github.com/citizen428/emacs

  9. ruby-on-rails - Rails 应用程序中的 Rails : How are you using application_controller. rb 是新手吗? - 2

    刚入门rails,开始慢慢理解。有人可以解释或给我一些关于在application_controller中编码的好处或时间和原因的想法吗?有哪些用例。您如何为Rails应用程序使用应用程序Controller?我不想在那里放太多代码,因为据我了解,每个请求都会调用此Controller。这是真的? 最佳答案 ApplicationController实际上是您应用程序中的每个其他Controller都将从中继承的类(尽管这不是强制性的)。我同意不要用太多代码弄乱它并保持干净整洁的态度,尽管在某些情况下ApplicationContr

  10. ruby-on-rails - 独立 ruby​​ 脚本的配置文件 - 2

    我有一个在Linux服务器上运行的ruby​​脚本。它不使用rails或任何东西。它基本上是一个命令行ruby​​脚本,可以像这样传递参数:./ruby_script.rbarg1arg2如何将参数抽象到配置文件(例如yaml文件或其他文件)中?您能否举例说明如何做到这一点?提前谢谢你。 最佳答案 首先,您可以运行一个写入YAML配置文件的独立脚本:require"yaml"File.write("path_to_yaml_file",[arg1,arg2].to_yaml)然后,在您的应用中阅读它:require"yaml"arg

随机推荐