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:
open
ve start
bunu yapmak için sırasıyla Mac OS / X ve Windows için komut yorumlayıcı şeylerdir.
Bunları Python'dan çağırmak için subprocess
modü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.quote
Unix 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 filename
da kaçması gereken yer.Bunları subprocess
modü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ı subprocess
nelerdir?
'filename ; rm -rf /'
" sorunu ve eğer dosya adı bozuk olabilir, kullanarak subprocess.call
bize biraz ek koruma sağlar.retcode
her 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 subprocess
tercih 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 start
komutunun , kullanmanın yararlarının çoğunu geçersiz kılan geçiş yapmanızı gerektirmesidir .shell=True
subprocess
filename
Formun 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.
subprocess
Python 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-open
aynı şeyi yapan bir komut da vardır , ancak xdg-open
Free 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.py
ve benim için firefox indirme iletişim kutusunu açtı. Sorun nedir? Manjaro linux kullanıyorum.
xdg-open
Yapı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.
startfile
iş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 location
Yolu 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.exe
programı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.call
yöntem tr parametreleri düzgün tırnak, start
komut 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.call
baş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))