ฉันต้องสามารถเปิดเอกสารโดยใช้แอปพลิเคชันเริ่มต้นใน Windows และ Mac OS โดยพื้นฐานแล้วฉันต้องการทำสิ่งเดียวกันกับที่เกิดขึ้นเมื่อคุณดับเบิลคลิกที่ไอคอนเอกสารใน Explorer หรือ Finder วิธีที่ดีที่สุดในการทำ Python คืออะไร?
ฉันต้องสามารถเปิดเอกสารโดยใช้แอปพลิเคชันเริ่มต้นใน Windows และ Mac OS โดยพื้นฐานแล้วฉันต้องการทำสิ่งเดียวกันกับที่เกิดขึ้นเมื่อคุณดับเบิลคลิกที่ไอคอนเอกสารใน Explorer หรือ Finder วิธีที่ดีที่สุดในการทำ Python คืออะไร?
คำตอบ:
open
และstart
เป็นตัวแปลคำสั่งสำหรับ Mac OS / X และ Windows ตามลำดับเพื่อทำสิ่งนี้
หากต้องการเรียกใช้จาก Python คุณสามารถใช้subprocess
โมดูลหรือos.system()
.
ข้อควรพิจารณาในการใช้แพ็คเกจมีดังนี้
คุณสามารถโทรหาพวกเขาผ่านทางos.system
ซึ่งใช้งานได้ แต่ ...
การ หลีกเลี่ยง:os.system
ใช้ได้เฉพาะกับชื่อไฟล์ที่ไม่มีช่องว่างหรือเมตาอักขระเชลล์อื่น ๆ ในชื่อพา ธ (เช่นA:\abc\def\a.txt
) มิฉะนั้นจะต้องใช้ Escape มีshlex.quote
ไว้สำหรับระบบที่เหมือน Unix แต่ไม่มีมาตรฐานสำหรับ Windows จริงๆ อาจเห็นpython, windows: การแยกวิเคราะห์บรรทัดคำสั่งด้วย shlex
os.system("open " + shlex.quote(filename))
os.system("start " + filename)
พูดอย่างถูกต้องfilename
ด้วยคุณยังสามารถโทรหาพวกเขาผ่านsubprocess
โมดูล แต่ ...
สำหรับ Python 2.7 และใหม่กว่าให้ใช้ไฟล์
subprocess.check_call(['open', filename])
ใน Python 3.5+ คุณสามารถใช้สิ่งที่ซับซ้อนกว่าเล็กน้อย แต่ก็ค่อนข้างหลากหลายกว่า
subprocess.run(['open', filename], check=True)
หากคุณจำเป็นต้องเข้ากันได้ตลอดทางกลับไปที่ Python 2.4 คุณสามารถใช้subprocess.call()
และดำเนินการตรวจสอบข้อผิดพลาดของคุณเอง:
try:
retcode = subprocess.call("open " + filename, shell=True)
if retcode < 0:
print >>sys.stderr, "Child was terminated by signal", -retcode
else:
print >>sys.stderr, "Child returned", retcode
except OSError, e:
print >>sys.stderr, "Execution failed:", e
ตอนนี้ข้อดีของการใช้subprocess
คืออะไร?
'filename ; rm -rf /'
" โดยธรรมชาติและหากชื่อไฟล์เสียหายได้การใช้subprocess.call
จะช่วยให้เราได้รับการป้องกันเพิ่มเติมเล็กน้อยretcode
กรณีทั้งสอง แต่พฤติกรรมในการเพิ่มข้อยกเว้นอย่างชัดเจนในกรณีของข้อผิดพลาดจะช่วยให้คุณสังเกตเห็นได้อย่างแน่นอนว่ามีความล้มเหลวหรือไม่ (แม้ว่าในบางสถานการณ์การย้อนกลับอาจไม่เป็นประโยชน์เลยมากกว่าการเพิกเฉยต่อข้อผิดพลาด)สำหรับการคัดค้าน "แต่subprocess
เป็นที่ต้องการ" อย่างไรก็ตามos.system()
ไม่ได้เลิกใช้งานและในแง่หนึ่งก็เป็นเครื่องมือที่ง่ายที่สุดสำหรับงานนี้โดยเฉพาะ สรุป: การใช้os.system()
จึงเป็นคำตอบที่ถูกต้องเช่นกัน
ข้อเสียที่ทำเครื่องหมายไว้คือstart
คำสั่งของWindows ต้องการให้คุณส่งผ่านshell=True
ซึ่งจะปฏิเสธประโยชน์ส่วนใหญ่ของการใช้งานsubprocess
ซึ่งขัดแย้งมากที่สุดของประโยชน์ของการใช้
filename
นี่คือตัวอย่างที่สมบูรณ์แบบว่าทำไม os.system () จึงไม่ปลอดภัยและไม่ปลอดภัยทั้งนี้ขึ้นอยู่กับที่มา กระบวนการย่อยจะดีกว่า
os.system()
คือมันใช้เชลล์ (และคุณไม่ได้ทำเชลล์หนีที่นี่สิ่งที่ไม่ดีจะเกิดขึ้นกับชื่อไฟล์ที่ถูกต้องอย่างสมบูรณ์ซึ่งมีเมตา - อักขระของเชลล์) เหตุผลที่เป็นที่ต้องการคือการที่คุณสามารถเลือกที่จะข้ามเปลือกโดยใช้subprocess.call()
subprocess.call(["open", filename])
สิ่งนี้ใช้ได้กับชื่อไฟล์ที่ถูกต้องทั้งหมดและไม่ทำให้เกิดช่องโหว่การแทรกเชลล์แม้กระทั่งสำหรับชื่อไฟล์ที่ไม่น่าเชื่อถือ
ใช้subprocess
โมดูลที่มีอยู่ใน Python 2.4+ ไม่ใช่os.system()
ดังนั้นคุณจึงไม่ต้องจัดการกับการหนีเชลล์
import subprocess, os, platform
if platform.system() == 'Darwin': # macOS
subprocess.call(('open', filepath))
elif platform.system() == 'Windows': # Windows
os.startfile(filepath)
else: # linux variants
subprocess.call(('xdg-open', filepath))
วงเล็บคู่เป็นเพราะsubprocess.call()
ต้องการลำดับเป็นอาร์กิวเมนต์แรกดังนั้นเราจึงใช้ทูเพิลที่นี่ บนระบบ Linux ที่มี Gnome ยังมีgnome-open
คำสั่งที่ทำสิ่งเดียวกัน แต่xdg-open
เป็นมาตรฐาน Free Desktop Foundation และใช้ได้กับสภาพแวดล้อมเดสก์ท็อป Linux
xdg-open
- linux.die.net/man/1/xdg-open
xdg-open test.py
และเปิดกล่องโต้ตอบดาวน์โหลด firefox ให้ฉัน มีอะไรผิดปกติ ฉันใช้ manjaro linux
xdg-open
การกำหนดค่าของคุณจะสับสน แต่นั่นไม่ใช่สิ่งที่เราสามารถแก้ไขได้ในความคิดเห็น อาจจะดูunix.stackexchange.com/questions/36380/…
ฉันชอบ:
os.startfile(path, 'open')
โปรดทราบว่าโมดูลนี้รองรับชื่อไฟล์ที่มีช่องว่างในโฟลเดอร์และไฟล์เช่น
A:\abc\folder with spaces\file with-spaces.txt
( python docs ) ไม่จำเป็นต้องเพิ่ม 'open' (เป็นค่าเริ่มต้น) เอกสารกล่าวถึงโดยเฉพาะว่าสิ่งนี้เหมือนกับการดับเบิลคลิกที่ไอคอนของไฟล์ใน Windows Explorer
โซลูชันนี้ใช้เฉพาะ Windows เท่านั้น
startfile
ฟังก์ชันนี้ไม่มีอยู่ด้วยซ้ำซึ่งหมายความว่าผู้ใช้จะได้รับข้อความแสดงข้อผิดพลาดที่ทำให้สับสนเกี่ยวกับฟังก์ชันที่หายไป คุณอาจต้องการตรวจสอบแพลตฟอร์มเพื่อหลีกเลี่ยงปัญหานี้
เพื่อความสมบูรณ์ (ไม่ได้อยู่ในคำถาม) xdg-openจะทำเช่นเดียวกันบน Linux
import os
import subprocess
def click_on_file(filename):
'''Open document with default application in Python.'''
try:
os.startfile(filename)
except AttributeError:
subprocess.call(['open', filename])
webbrowser
หากคุณมีการใช้วิธีการแก้ปัญหาคุณอาจพิจารณา
เป็นไลบรารีมาตรฐานและแม้จะมีชื่อ แต่ก็ยังพยายามเปิดไฟล์:
โปรดทราบว่าในบางแพลตฟอร์มการพยายามเปิดชื่อไฟล์โดยใช้ฟังก์ชันนี้อาจใช้งานได้และเริ่มโปรแกรมที่เกี่ยวข้องกับระบบปฏิบัติการ อย่างไรก็ตามสิ่งนี้ไม่ได้รับการสนับสนุนหรือพกพา ( อ้างอิง )
ฉันลองใช้รหัสนี้และใช้งานได้ดีใน Windows 7 และ Ubuntu Natty:
import webbrowser
webbrowser.open("path_to_file")
รหัสนี้ยังใช้งานได้ดีใน Windows XP Professional โดยใช้ Internet Explorer 8
open location
ที่นั่นควรใช้งานได้หากคุณให้เส้นทางเป็น URL ที่ถูกต้อง
import webbrowser webbrowser.open("file:///Users/nameGoesHere/Desktop/folder/file.py")
หากคุณต้องการไปsubprocess.call()
ทางนั้นควรมีลักษณะเช่นนี้ใน Windows:
import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))
คุณไม่สามารถใช้:
subprocess.call(('start', FILE_NAME))
เนื่องจากstart
ไม่ใช่ปฏิบัติการแต่เป็นคำสั่งของcmd.exe
โปรแกรม ใช้งานได้:
subprocess.call(('cmd', '/C', 'start', FILE_NAME))
แต่ถ้าไม่มีช่องว่างใน FILE_NAME
ในขณะที่subprocess.call
method enอ้างถึงพารามิเตอร์อย่างถูกต้อง แต่start
คำสั่งมีไวยากรณ์ที่ค่อนข้างแปลกโดยที่:
start notes.txt
ทำอย่างอื่นที่ไม่ใช่:
start "notes.txt"
สตริงที่ยกมาชุดแรกควรตั้งชื่อของหน้าต่าง เพื่อให้มันใช้งานได้กับช่องว่างเราต้องทำ:
start "" "my notes.txt"
ซึ่งเป็นสิ่งที่โค้ดด้านบนทำ
Start ไม่รองรับชื่อพา ธ แบบยาวและช่องว่าง คุณต้องแปลงเป็น 8.3 เส้นทางที่เข้ากันได้
import subprocess
import win32api
filename = "C:\\Documents and Settings\\user\\Desktop\file.avi"
filename_short = win32api.GetShortPathName(filename)
subprocess.Popen('start ' + filename_short, shell=True )
ต้องมีไฟล์เพื่อทำงานกับการเรียก API
start "Title" "C:\long path to\file.avi"
ฉันค่อนข้างสายไปมาก แต่นี่คือวิธีแก้ปัญหาโดยใช้ windows api สิ่งนี้จะเปิดแอปพลิเคชันที่เกี่ยวข้องเสมอ
import ctypes
shell32 = ctypes.windll.shell32
file = 'somedocument.doc'
shell32.ShellExecuteA(0,"open",file,0,0,5)
ค่าคงที่เวทย์มนตร์จำนวนมาก ศูนย์แรกคือ hwnd ของโปรแกรมปัจจุบัน สามารถเป็นศูนย์ อีกสองศูนย์เป็นพารามิเตอร์ทางเลือก (พารามิเตอร์และไดเร็กทอรี) 5 == SW_SHOW ระบุวิธีเรียกใช้งานแอป อ่าน เอกสาร ShellExecute APIสำหรับข้อมูลเพิ่มเติม
os.startfile(file)
อะไร?
os.startfile(path, 'open')
ภายใต้ Windows เป็นสิ่งที่ดีเนื่องจากเมื่อมีช่องว่างในไดเรกทอรีos.system('start', path_name)
ไม่สามารถเปิดแอปได้อย่างถูกต้องและเมื่อมี i18n อยู่ในไดเรกทอรีos.system
จำเป็นต้องเปลี่ยน Unicode เป็นตัวแปลงสัญญาณของคอนโซลใน Windows
บน Mac OS คุณสามารถเรียก 'เปิด'
import os
os.popen("open myfile.txt")
สิ่งนี้จะเปิดไฟล์ด้วย TextEdit หรือแอพใดก็ตามที่ตั้งเป็นค่าเริ่มต้นสำหรับประเภทไฟล์นี้
หากคุณต้องการระบุแอปเพื่อเปิดไฟล์ด้วยบน Mac OS X ให้ใช้สิ่งนี้:
os.system("open -a [app name] [file name]")
บน windows 8.1 ด้านล่างใช้งานได้ในขณะที่วิธีอื่น ๆ ที่มีsubprocess.call
ล้มเหลวด้วยพา ธ มีช่องว่างอยู่
subprocess.call('cmd /c start "" "any file path with spaces"')
ด้วยการใช้คำตอบนี้และคำตอบของผู้อื่นก่อนหน้านี้นี่คือรหัสอินไลน์ที่ใช้งานได้กับหลายแพลตฟอร์ม
import sys, os, subprocess
subprocess.call(('cmd /c start "" "'+ filepath +'"') if os.name is 'nt' else ('open' if sys.platform.startswith('darwin') else 'xdg-open', filepath))