我有一個Python腳本,我想通過點擊某個東西或通過刪除一個我想在該東西上打開的文件來啓動。我也想避免討厭的mac Python問題,即解釋器的名字(Python)而不是腳本的名字。我不想使用py2app,因爲我不想捆綁Python,並希望python文件保持爲文本文件。我想要一個純Python(或最好的shell腳本解決方案。)This顯示瞭如何做所有事情,但拖放部分; this顯示瞭如何通過創建一個允許控制圖標的包來執行相同操作。在Mac上,如何爲MenuBar(等)中腳本名稱而不是Python顯示的python腳本創建拖放應用程序?
6
A
回答
2
我對我的問題有一個答案,但我希望有人能想出一些不太複雜的東西。我想出的解決方案是創建AppleScript(Python)的Python腳本,將其編譯爲一個包,然後修改該包以更改允許的文件擴展名,圖標等等。
我沒有找到一種方法來獲得當啓動一個wxpython腳本,沒有AppleScript(或使用py2app)時的拖放工作,我無法讓AppleScript在我創建的包中工作,我不得不使用osacompile爲我創建捆綁軟件。
我喜歡更好的方法here或here,其中一個創建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?
2
通過覆蓋wx.App對象的MacOpenFiles方法可以處理應用程序圖標上的文件的DnD。
在lib/python2.7/plat-mac中的Python庫中存在一個腳本,名爲bundlebuilder.py,可用於幫助您構建應用程序包。它是從OSX的早期開始的,並且在某些方面可能已經過時,但是它在我最後一次嘗試它的時候起作用了。
相關問題
- 1. 如何通過Python爲Python腳本創建Mac應用程序包
- 2. 如何在Mac上的Python腳本中創建硬鏈接?
- 3. 如何在不顯示Python應用程序的情況下運行Python腳本?
- 4. 使用Python和腳本應用程序(在Mac上)
- 5. 如何從python腳本創建應用程序(exe)的linux
- 6. 創建python腳本爲exe
- 7. Python應用程序中的腳本
- 8. Python用戶創建腳本
- 9. 更改python腳本的進程名稱
- 10. 更改Python腳本的進程名稱
- 11. python腳本的管道名稱到python
- 12. Python作爲Python應用程序中的最終用戶腳本
- 13. 如何從Python 3中退出程序(不是Python腳本)?
- 14. python腳本在azure上創建表格
- 15. 用Python腳本在Ubuntu終端中顯示UTF8腳本
- 16. 拖放文件到Python腳本
- 17. python創建系統別名到腳本
- 18. 如何從不同的python腳本調用python腳本?
- 19. python腳本來創建fdf
- 20. 在Mac/Windows上運行Python腳本
- 21. 在Mac終端上運行Python腳本
- 22. 在Mac OS上執行Python GIMP腳本
- 23. 如何在iOS應用程序中調用python腳本?
- 24. 爲簡單的python腳本創建GUI
- 25. 運行在Python腳本中創建的KML腳本
- 26. Node.js應用程序與python腳本
- 27. 如何爲python腳本的requests.get創建php響應
- 28. 如何將Python 3腳本轉換爲Mac OS應用程序包?
- 29. 如何在.NET應用程序中執行python腳本..?
- 30. 在Python Web應用程序中嵌入python/dsl腳本
我對此有點困惑。當我最初嘗試一個測試腳本時,我認爲覆蓋MacOpenFiles會做我想做的事情,但是在我的項目中實現它之後,似乎MacOpenFiles只響應在應用程序已經運行時被刪除的文件。 – bht