Windows ve Mac OS'de varsayılan uygulamasını kullanarak bir belgeyi açabilmem gerekiyor. Temel olarak, Explorer veya Finder'da belge simgesine çift tıkladığınızda olanla aynı şeyi yapmak istiyorum. Bunu Python'da yapmanın en iyi yolu nedir?
Windows ve Mac OS'de varsayılan uygulamasını kullanarak bir belgeyi açabilmem gerekiyor. Temel olarak, Explorer veya Finder'da belge simgesine çift tıkladığınızda olanla aynı şeyi yapmak istiyorum. Bunu Python'da yapmanın en iyi yolu nedir?
Yanıtlar:
openve startbunu yapmak için sırasıyla Mac OS / X ve Windows için komut yorumlayıcı şeylerdir.
Bunları Python'dan çağırmak için subprocessmodül veya os.system().
İşte hangi paketin kullanılacağıyla ilgili dikkat edilmesi gereken noktalar:
Onları şu şekilde arayabilirsin os.system, ama ...
Kaçış: os.system yalnızca yol adında boşluk veya başka kabuk meta karakterleri olmayan dosya adlarıyla çalışır (örn. A:\abc\def\a.txt), Aksi takdirde bunların öncelenmesi gerekir. Orada shlex.quoteUnix benzeri sistemler için, ancak Windows için hiçbir şey gerçekten standardı. Belki ayrıca python, windows: shlex ile komut satırlarını ayrıştırma
os.system("open " + shlex.quote(filename))os.system("start " + filename)düzgün konuşmanın filenameda kaçması gereken yer.Bunları subprocessmodül aracılığıyla da arayabilirsiniz , ancak ...
Python 2.7 ve daha yenisi için şunu kullanın:
subprocess.check_call(['open', filename])
Python 3.5+ ile biraz daha karmaşık ama aynı zamanda biraz daha çok yönlü olanı eşit olarak kullanabilirsiniz.
subprocess.run(['open', filename], check=True)
Python 2.4'e kadar tamamen uyumlu olmanız gerekiyorsa subprocess.call(), kendi hata kontrolünüzü kullanabilir ve uygulayabilirsiniz:
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
Şimdi kullanmanın avantajları subprocessnelerdir?
'filename ; rm -rf /'" sorunu ve eğer dosya adı bozuk olabilir, kullanarak subprocess.callbize biraz ek koruma sağlar.retcodeher iki durumda da bağlıyız; ancak bir hata durumunda açıkça bir istisna oluşturma davranışı, bir hata olup olmadığını fark etmenize kesinlikle yardımcı olacaktır (ancak bazı senaryolarda, bir geri bildirim, hatayı göz ardı etmekten daha fazla yardımcı olmayabilir).İtiraza "Ama subprocesstercih edilir." Ancak, os.system()kullanımdan kaldırılmamıştır ve bir bakıma bu belirli iş için en basit araçtır. Sonuç: os.system()bu nedenle kullanmak da doğru bir cevaptır.
Belirgin bir dezavantaj , Windows startkomutunun , kullanmanın yararlarının çoğunu geçersiz kılan geçiş yapmanızı gerektirmesidir .shell=Truesubprocess
filenameFormun nereden geldiğine bağlı olarak bu, os.system () işlevinin neden güvensiz ve kötü olduğuna dair mükemmel bir örnektir. alt işlem daha iyidir.
os.system(), kabuğu kullanmasıdır (ve burada herhangi bir kabuk kaçışı yapmıyorsunuz, bu nedenle Kabuk meta karakterleri içeren mükemmel şekilde geçerli dosya adları için Bad Things gerçekleşecek). subprocess.call()Tercih edilmesinin nedeni , kullanarak kabuğu atlatma seçeneğinizin olmasıdır subprocess.call(["open", filename]). Bu, tüm geçerli dosya adları için çalışır ve güvenilmeyen dosya adları için bile bir kabuk enjeksiyon güvenlik açığı oluşturmaz.
subprocessPython 2.4+ üzerinde bulunan modülü kullanın os.system(), bu yüzden kabuk kaçışıyla uğraşmak zorunda kalmazsınız.
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))
Çift parantezler subprocess.call(), ilk argüman olarak bir dizi istediği için, bu yüzden burada bir demet kullanıyoruz. Gnome ile Linux sistemlerinde gnome-openaynı şeyi yapan bir komut da vardır , ancak xdg-openFree Desktop Foundation standardıdır ve Linux masaüstü ortamlarında çalışır.
xdg-open- linux.die.net/man/1/xdg-open
xdg-open test.pyve benim için firefox indirme iletişim kutusunu açtı. Sorun nedir? Manjaro linux kullanıyorum.
xdg-openYapılandırmanızın kafası karışmış gibi görünüyor , ancak bu gerçekten bir yorumda giderebileceğimiz bir şey değil. Belki bkz. Unix.stackexchange.com/questions/36380/…
Tercih ederim:
os.startfile(path, 'open')
Bu modülün, klasörlerinde ve dosyalarında boşluklar olan dosya adlarını desteklediğini unutmayın.
A:\abc\folder with spaces\file with-spaces.txt
( python docs ) 'open' eklenmek zorunda değildir (bu varsayılandır). Dokümanlar özellikle bunun Windows Gezgini'nde bir dosya simgesine çift tıklamaya benzediğini belirtiyor.
Bu çözüm yalnızca pencerelerdir.
startfileişlev mevcut değildir, bu da kullanıcıların eksik bir işlevle ilgili kafa karıştırıcı bir hata mesajı alacağı anlamına gelir. Bundan kaçınmak için platformu kontrol etmek isteyebilirsiniz.
Sırf bütünlük için (söz konusu değildi), xdg-open aynı şeyi Linux'ta yapacak.
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])
Sezgisel bir yöntem kullanmanız gerekiyorsa, düşünebilirsiniz webbrowser.
Standart kitaplıktır ve adına rağmen dosyaları açmaya çalışır:
Bazı platformlarda, bu işlevi kullanarak bir dosya adını açmaya çalışmanın, çalışabileceğini ve işletim sisteminin ilişkili programını başlatabileceğini unutmayın. Ancak bu ne desteklenmekte ne de taşınabilir. ( Referans )
Bu kodu denedim ve Windows 7 ve Ubuntu Natty'de iyi çalıştı:
import webbrowser
webbrowser.open("path_to_file")
Bu kod, Internet Explorer 8 kullanılarak Windows XP Professional'da da sorunsuz çalışır.
open locationYolu geçerli bir url olarak verirseniz çalışması gereken orada kullanır .
import webbrowser webbrowser.open("file:///Users/nameGoesHere/Desktop/folder/file.py")
Yolunuza gitmek istiyorsanız subprocess.call(), Windows'ta şöyle görünmelidir:
import subprocess
subprocess.call(('cmd', '/C', 'start', '', FILE_NAME))
Sadece kullanamazsınız:
subprocess.call(('start', FILE_NAME))
çünkü start çalıştırılabilir değil, cmd.exeprogramın bir komutu . Bu çalışıyor:
subprocess.call(('cmd', '/C', 'start', FILE_NAME))
ancak yalnızca FILE_NAME dosyasında boşluk yoksa.
İken subprocess.callyöntem tr parametreleri düzgün tırnak, startkomut oldukça garip bir sözdizimi vardır:
start notes.txt
şunlardan başka bir şey yapar:
start "notes.txt"
İlk alıntılanan dize, pencerenin başlığını belirlemelidir. Alanlarla çalışmasını sağlamak için şunları yapmalıyız:
start "" "my notes.txt"
üstteki kodun yaptığı da budur.
Başlangıç, uzun yol adlarını ve beyaz boşlukları desteklemez. 8.3 uyumlu yollara dönüştürmelisiniz.
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 çağrısıyla çalışabilmesi için dosyanın var olması gerekir.
start "Title" "C:\long path to\file.avi"
Çok geç kaldım ama işte windows api kullanarak bir çözüm. Bu her zaman ilişkili uygulamayı açar.
import ctypes
shell32 = ctypes.windll.shell32
file = 'somedocument.doc'
shell32.ShellExecuteA(0,"open",file,0,0,5)
Bir sürü sihirli sabit. İlk sıfır, mevcut programın hwnd'sidir. Sıfır olabilir. Diğer iki sıfır isteğe bağlı parametrelerdir (parametreler ve dizin). 5 == SW_SHOW, uygulamanın nasıl çalıştırılacağını belirtir. Daha fazla bilgi için ShellExecute API belgelerini okuyun .
os.startfile(file)?
Dosyayı Mac OS X'te açacağınız uygulamayı belirtmek istiyorsanız, şunu kullanın:
os.system("open -a [app name] [file name]")
Windows 8.1'de, yol ile subprocess.callbaşarısız olan diğer verilen yollar içinde boşluklar varken, aşağıda çalıştı .
subprocess.call('cmd /c start "" "any file path with spaces"')
Bunu ve diğerlerinin yanıtlarını daha önce kullanarak, işte birden çok platformda çalışan bir satır içi kod.
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))