Python'da geçerli komut dosyasının adını alma


407

Şu anda çalışan Python betiğinin adını almaya çalışıyorum.

Denilen bir komut dosyası var ve komut foo.pydosyası adını almak için böyle bir şey yapmak istiyorum:

print Scriptname

Yanıtlar:


620

__file__Geçerli dosyanın adını almak için kullanabilirsiniz . Ana modülde kullanıldığında, başlangıçta çağrılan komut dosyasının adıdır.

Dizin kısmını (varsa) atlamak istiyorsanız, kullanabilirsiniz os.path.basename(__file__).


15
Python 3.2: " Exception NameError: NameError("global name '__file__' is not defined",)"
sdaau

20
@sdaau: __file__interaktif tercümanda tanımlanmamıştır, çünkü orada anlamsızdır. İçe aktarma uygulaması tarafından ayarlanır, bu nedenle standart olmayan bir içe aktarma mekanizması kullanırsanız da ayarlanmamış olabilir.
Sven Marnach

8
En azından Python 2.7 için, bunun import osçalışması için bir gerekli olduğuna inanıyorum . Bunu cevaba eklerdim.
Nick Chammas

14
@ cdunn2001: import osve import os.pathtamamen eşdeğerdir.
Sven Marnach

2
@ sven-marnach: Oh, haklısın . Yıllardır yanlış yapıyorum!
cdunn2001

136
import sys
print sys.argv[0]

Bu yazdırılacaktır foo.pyiçin python foo.py, dir/foo.pyiçin python dir/foo.pybu ilk argüman var vb python. (Py2exe sonra olacağını unutmayın foo.exe.)


33
@DenisMalinovsky: "işe yaramaz" ı tanımlayın. Eğer ararsanız python linkfile.py, nereye linkfile.pysembolik köprü ise realfile.py, sys.argv[0]olacak 'linkfile.py'ya ne istediğinizi olabilir veya olmayabilir; kesinlikle beklediğim bu . __file__aynı: olacak linkfile.py. Eğer bulmak istiyorsanız 'realfile.py'den 'linkfile.py'deneyin os.path.realpath('linkfile.py').
Chris Morgan

6
+1, çünkü (a) biraz daha temiz ve (b) modülde çalışmaya devam eder (burada dosya değişkeni yürütülen dosya değil, modül dosyası olur).
Robert

Bu cevap güzel çünkü IDLE'de de çalışıyor. Not olarak, sadece dosya
adını

Daha da önemlisi, bu, ana dosyanın içinden çalışmaz. Bunu kullanmayın, __file__onun yerine kullanın.
Apollys, Monica

NE!!! Bunu denedin mi? Tam tersi doğrudur. Soru soran, şu anda yürütülmekte olan python dosyasının değil, çalışan python betiğinin adını istedi. Bir hata oluştuğunda, komut dosyası adını izin verilen bağımsız değişkenlerle birlikte yazdıran bir komut dosyanız olduğunu düşünün. Bunu, bu 2 teknikten birini kullanarak bir işleve yerleştirdiniz. Bir noktada, işlevi harici bir kütüphaneye taşımaya karar verdiniz. Çalışan ana komut dosyasının adını veya yürütülmekte olan kitaplık dosyasının adını yazdırmak ister misiniz?
John Deighan

71

Tamlık uğruna, çeşitli olası sonuçları özetlemeye ve her birinin tam davranışı için referanslar sağlamaya değeceğini düşündüm:

  • __file__resmi belgelerde ayrıntılı olarak açıklandığı gibi şu anda yürütülen dosyadır :

    __file__bir dosyadan yüklendiyse modülün yüklendiği dosyanın yol adıdır. __file__Nitelik gibi modülleri, belirli türleri için eksik olabilir C statik tercüman içine bağlantılı modüllerin; paylaşılan bir kitaplıktan dinamik olarak yüklenen uzantı modülleri için, paylaşılan kitaplık dosyasının yol adıdır.

    Python3.4 itibaren itibaren, başına konuyla 18416 , __file__şu anda yürütülen dosyası (değil ile tercüman aracılığıyla doğrudan idam edilmiş bir senaryo olmadığı sürece, her zaman mutlak bir yoldur -mgöreli bir yol kullanarak komut satırı seçeneği).

  • __main__.__file__(içe aktarmayı gerektirir __main__) ana modülün , örneğin komut satırından çağrılan komut dosyasının yukarıda belirtilen __file__özniteliğine erişir .

  • sys.argv[0](içe aktarmayı gerektirir sys) komut satırından çağrılan komut dosyası adıdır ve resmi belgelerde ayrıntılı olarak açıklandığı gibi mutlak bir yol olabilir :

    argv[0]komut dosyası adıdır (bunun tam yol adı olup olmadığı işletim sistemine bağlıdır). Komut -cyorumlayıcıya komut satırı seçeneği kullanılarak yürütüldüyse argv[0], dizeye ayarlanır '-c'. Python yorumlayıcısına komut dosyası adı geçmediyse argv[0], boş dizedir.

    Bahsedildiği gibi bu soruya başka bir cevap , Python gibi araçları vasıtasıyla tek başına çalıştırılabilir programlara dönüştürüldü komut py2exe veya PyInstaller bu yaklaşımı kullanırken (yani istenilen sonucu göstermeyebilir sys.argv[0]adı yerine çalıştırılabilir adını yapacağını yürütülebilir dosya içindeki ana Python dosyasının).

  • Yukarıda belirtilen seçeneklerin hiçbiri, muhtemelen düzensiz bir içe aktarma işleminden dolayı işe yaramıyorsa, denetleme modülü yararlı olabilir. Özellikle, yürütmesini inspect.getfile(...)ile inspect.currentframe()ikinci olsa da, işe yarayabilir geriNone olmayan bir uygulama çalışırken Python yığın çerçevesi.


Sembolik bağlantıları kullanma

Geçerli komut dosyası sembolik bir bağlantıysa, yukarıdakilerin tümü gerçek dosyanın yolu yerine sembolik bağın yolunu döndürür os.path.realpath(...)ve ikincisini ayıklamak için çağrılmalıdır.


Gerçek dosya adını ayıklayan diğer manipülasyonlar

os.path.basename(...)asıl dosya adını ayıklamak için yukarıdakilerden herhangi birine os.path.splitext(...)çağrılabilir ve sonekini olduğu gibi kesmek için asıl dosya adına çağrılabilir os.path.splitext(os.path.basename(...)).

Kaynaktan Python 3.4 itibaren, her PEP 428 , PurePathsınıf ve pathlibmodülü de yukarıdakilerin herhangi olduğu gibi kullanılabilir. Özellikle, pathlib.PurePath(...).namegerçek dosya adını alır ve pathlib.PurePath(...).stemgerçek dosya adını soneki olmadan ayıklar.


66

Not __file__ana dosyadan ithal ve farklı olabilir bu kod bulunduğu, yorumlanıyor dosyayı verecektir. Ana dosyayı almak için özel __main__ modülü kullanılabilir:

import __main__ as main
print(main.__file__)

O Not __main__.__file__taşınabilir hale getirmek için yukarıdaki gibi Python 2.7 değil 3.2 eserler, bu nedenle ithalat-olarak sözdizimi kullanın.


Bu pek çok durumda çalışır, ancak rPythonpaketi Rdilden kullandığımda çalışmaz . Bu, ele alınması çok zor olan istisnai bir durum olmalıdır.
Leonid

Gerçekten de, rPython paketi python yorumlayıcısını gömer; bu, python kendi başına çalışırken olduğu gibi bir 'ana' dosya olmadığı anlamına gelir (python gömüldüğünde aynı davranışı bulacaksınız). __main__Değişkenleri Rve arasında geçişte kullanmak için dahili olarak içe aktarır, pythonbu nedenle __main__.__file__başka bir şey çağırmadan önce ayarlanması nispeten kolaydır , ancak bu durumda neyin uygun bir değer olacağından bile emin değilim.
Perkins

42

Yukarıdaki cevaplar iyidir. Ancak yukarıdaki sonuçları kullanarak bu yöntemi daha verimli buldum.
Bu, gerçek komut dosyası adının yolla sonuçlanmasına neden olmaz.

import sys    
import os    
file_name =  os.path.basename(sys.argv[0])

1
Uzantıyı da bölmeyi seviyorum, bu yüzden şunu kullanıyorum: os.path.splitext (os.path.basename (sys.argv [0])) [0]
RufusVS

19

Modern Python sürümleri (3.4+) Path(__file__).nameiçin daha deyimsel olmalıdır. Ayrıca, uzantısız Path(__file__).stemkomut dosyası adını verir .py.


NameError: 'Yol' tanımlanmadı
RufusVS

5
Önce sen yapmalısın from pathlib import Path.
Emil Melnikov

"modern" Python 3.x demek?
einpoklum

1
@einpoklum pathlibPython 3.4'te tanıtıldı, bu yüzden Python 3.4'ten başlamalı .
Andrey Semakin


9

Not: Python 3+ kullanıyorsanız, bunun yerine print () işlevini kullanmalısınız

Dosya adının olduğu varsayıldığında foo.py, aşağıdaki snippet

import sys
print sys.argv[0][:-3]

veya

import sys
print sys.argv[0][::-1][3:][::-1]

Daha fazla karakter içeren diğer uzantılara gelince, örneğin dosya adı foo.pypy

import sys
print sys.argv[0].split('.')[0]

Mutlak bir yoldan çıkarmak istiyorsanız

import sys
print sys.argv[0].split('/')[-1].split('.')[0]

çıktı olacak foo


1
sys.argv [0] [: - 3] yapardı
kon psych

@konpsych daha zarif
xtonousou

Orada arasındaki büyük bir fark var __file__ve sys.argv[0]Görmekten stackoverflow.com/questions/5851588/...
Maksym Ganenko

8

Sys içindeki ilk argüman geçerli dosya adı olacak, bu yüzden bu işe yarayacak

   import sys
   print sys.argv[0] # will print the file name

7

Alışılmadık bir içe aktarma işlemi gerçekleştiriyorsanız (örn., Bir seçenekler dosyasıdır), şunu deneyin:

import inspect
print (inspect.getfile(inspect.currentframe()))

Bunun, dosyanın mutlak yolunu döndüreceğini unutmayın.


3

uzantı olmadan mevcut komut dosyası adını almak için bunu deneyebiliriz.

import os

script_name = os.path.splitext(os.path.basename(__file__))[0]

2

OP mevcut komut dosyasının adını istediğinden, tercih ederim

import os
os.path.split(sys.argv[0])[1]

1

tüm bu cevaplar harika, ama bazı problemleri var İlk bakışta göremeyebilirsiniz.

ne istediğimizi tanımlayalım - yürürlükteki modülün adını değil, yürütülen kodun adını istiyoruz - bu nedenle __file__, içe aktarılan bir modülde değil, yalnızca yürütülen kodda kullanılıyorsa çalışır. sys.argvşüpheli - programınız pytest tarafından çağrılmışsa? veya pydoc koşucusu mu? veya uwsgi tarafından çağrılmışsa?

ve - komut dosyası adını almak için üçüncü bir yöntem var, cevaplarda görmedim - Yığını inceleyebilirsiniz.

Başka bir sorun, Siz (veya başka bir program) sys.argvve__main__.__file__ - mevcut olabilir, olmayabilir. Geçerli olabilir ya da olmayabilir. En azından Betiğin (istenen sonuç) var olup olmadığını kontrol edebilirsiniz!

github'daki kütüphanem bitranox / lib_programname tam olarak bunu yapar:

  • __main__mevcut olup olmadığını kontrol et
  • __main__.__file__mevcut olup olmadığını kontrol et
  • __main__.__file__geçerli bir sonuç veriyor mu (bu komut dosyası var mı?)
  • değilse: sys.argv'yi kontrol edin:
  • sys.argv'de pytest, docrunner, vb. var mı? -> evet ise, bunu görmezden gelin
  • burada geçerli bir sonuç alabilir miyiz?
  • değilse: yığını inceleyin ve sonucu oradan alın
  • yığın da geçerli bir sonuç vermezse, bir İstisna atın.

Bu arada, bu benim çözüm şimdiye kadar çalışıyor setup.py test, uwsgi, pytest, pycharm pytest, pycharm docrunner (doctest), dreampie,eclipse

Hamur Hellman'ın "Python'dan Bir Sürecin Adının Belirlenmesi" konulu güzel bir blog makalesi de var


0

Hızlı kirli çözümüm:

__file__.split('/')[-1:][0]

2
os.pathDosya adlarını bölmek için daha iyi kullanım
Maksym Ganenko


0

Python 3.5'ten itibaren şunları yapabilirsiniz:

from pathlib import Path
Path(__file__).stem

Buradan daha fazlasını görün: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem

Örneğin, kullanıcı dizinim altında test.pybununla adlandırılmış bir dosya var:

from pathlib import Path

print(Path(__file__).stem)
print(__file__)

bu çıktıları çalıştırmak:

>>> python3.6 test.py
test
test.py
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.