Получить имя текущего скрипта с Python

Я пытаюсь получить имя скрипта Python, который в данный момент выполняется.

Например, у меня есть скрипт с именем foo.py и я хотел бы сделать что-то вроде этого внутри:

print Scriptname

и получить: foo.py,

19 ответов

Решение

Использование __file__, Если вы хотите опустить часть каталога (которая может присутствовать), вы можете использовать os.path.basename(__file__),

import sys
print sys.argv[0]

Это напечатает foo.py за python foo.py, dir/foo.py за python dir/foo.pyи т. д. Это первый аргумент python, (Обратите внимание, что после py2exe это будет foo.exe.)

Для полноты картины я подумал, что было бы целесообразно обобщить различные возможные результаты и предоставить ссылки для точного поведения каждого из них:

  • __file__ это исполняемый файл, как указано в официальной документации:

    __file__ путь к файлу, из которого был загружен модуль, если он был загружен из файла. __file__ атрибут может отсутствовать для определенных типов модулей, таких как модули C, которые статически связаны с интерпретатором; для модулей расширения, загружаемых динамически из общей библиотеки, это путь к файлу общей библиотеки.

    Начиная с Python3.4, за выпуск 18416, __file__ всегда является абсолютным путем, если только исполняемый файл не является скриптом, который был выполнен напрямую (не через интерпретатор с -m опция командной строки) с использованием относительного пути.

  • __main__.__file__ (требуется импорт __main__) просто получает доступ к вышеупомянутому __file__ атрибут основного модуля, например, сценария, который был вызван из командной строки.

  • sys.argv[0] (требуется импорт sys) - это имя скрипта, которое было вызвано из командной строки и может быть абсолютным путем, как подробно описано в официальной документации:

    argv[0] имя скрипта (зависит от операционной системы, является ли это полным путем или нет). Если команда была выполнена с использованием -c опция командной строки для интерпретатора, argv[0] установлен на строку '-c', Если имя скрипта не было передано интерпретатору Python, argv[0] пустая строка

    Как уже упоминалось в другом ответе на этот вопрос, сценарии Python, которые были преобразованы в автономные исполняемые программы с помощью таких инструментов, как py2exe или PyInstaller, могут не отображать желаемый результат при использовании этого подхода (т.е. sys.argv[0] будет содержать имя исполняемого файла, а не имя основного файла Python в этом исполняемом файле).


os.path.basename() может быть вызван любым из вышеперечисленных для извлечения фактического имени файла.

Обратите внимание, что __file__ даст файл, в котором находится этот код, который можно импортировать и отличать от интерпретируемого основного файла. Чтобы получить основной файл, можно использовать специальный модуль __main__:

import __main__ as main
print(main.__file__)

Обратите внимание, что __main__.__file__ работает в Python 2.7, но не в 3.2, поэтому используйте синтаксис import-as, как описано выше, чтобы сделать его переносимым.

Вышеуказанные ответы хороши. Но я нашел этот метод более эффективным, используя приведенные выше результаты.
Это приводит к фактическому имени файла сценария, а не к пути.

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

Для современных версий Python, Path(__file__).name должно быть более идиоматичным. Также, Path(__file__).stem дает вам имя сценария без .py расширение.

Начиная с Python 3.5, вы можете просто:

from pathlib import Path
Path(__file__).stem

Подробнее см. Здесь: https://docs.python.org/3.5/library/pathlib.html

Например, в моем пользовательском каталоге есть файл с именем test.py с этим внутри:

from pathlib import Path

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

запуск этих выходов:

>>> python3.6 test.py
test
test.py

Если вы делаете необычный импорт (например, это файл опций), попробуйте:

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

Обратите внимание, что это вернет абсолютный путь к файлу.

Попробуй это:

print __file__

Предполагая, что имя файла foo.pyнижеприведенный фрагмент

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

или же

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

будет выводить foo

Первый аргумент в sys будет текущим именем файла, так что это будет работать

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

Вы можете сделать это без импорта операционной системы или других библиотек.

Если вы хотите получить путь к текущему скрипту Python, используйте: __file__

Если вы хотите получить только имя файла без расширения.py, используйте это:

__file__.rsplit("/", 1)[1].split('.')[0]

Мы можем попробовать это, чтобы получить текущее имя скрипта без расширения.

import os

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

Все эти ответы хороши, но есть некоторые проблемы, которые вы можете не заметить с первого взгляда.

позволяет определить, что мы хотим - нам нужно имя выполняемого скрипта, а не имя текущего модуля - поэтому __file__ будет работать, только если он используется в исполняемом скрипте, а не в импортированном модуле.sys.argvтакже сомнительно - что, если бы ваша программа была вызвана pytest? или pydoc runner? или если он был вызван uwsgi?

и - есть третий метод получения имени скрипта, который я не видел в ответах - вы можете проверить стек.

Другая проблема заключается в том, что Вы (или какая-либо другая программа) можете вмешиваться в sys.argv а также __main__.__file__- может быть, а может и нет. Это может быть действительным или нет. По крайней мере, Вы можете проверить, существует ли скрипт (желаемый результат)!

библиотека lib_programname делает именно это:

  • проверить, если __main__ настоящее
  • проверить, если __main__.__file__ настоящее
  • дает __main__.__file__ действительный результат (существует ли этот сценарий?)
  • если нет: проверьте sys.argv:
  • есть ли в sys.argv pytest, docrunner и т. д.? -> если да, игнорируйте это
  • можем ли мы получить здесь достоверный результат?
  • если нет: проверьте стек и, возможно, получите результат оттуда
  • если также стек не дает допустимого результата, то генерирует исключение.

таким образом, мое решение пока работает с setup.py test, uwsgi, pytest, pycharm pytest, pycharm docrunner (doctest), dreampie, eclipse

есть также хорошая статья в блоге об этой проблеме от Dough Hellman, "Определение имени процесса из Python"

Кстати, он снова изменится в python 3.9: атрибут файлаосновного модуля стал абсолютным путем, а не относительным путем. Эти пути теперь остаются действительными после изменения текущего каталога с помощью os.chdir()

Поэтому я предпочитаю позаботиться об одном небольшом модуле, вместо того, чтобы просматривать мою кодовую базу, если ее нужно что-то изменить...


Отказ от ответственности: я являюсь автором библиотеки lib_programname.

Поскольку OP запросил имя текущего файла сценария, я бы предпочел

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

Мое быстрое грязное решение:

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

os.path.abspath(__file__) даст вам абсолютный путь (relpath() доступно также).

sys.argv[-1] даст вам относительный путь.

если вы получите путь к сценарию в базовом классе, используйте этот код, подкласс правильно получит путь к сценарию.

      sys.modules[self.__module__].__file__
 def basename():
   x=__file__
   y=x.split('\\')
   y1=y[-1]
   y2=y1.split('.')
   y3=y2[0]
 return(y2[0])
  
Другие вопросы по тегам