Получить имя текущего скрипта с 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()))
Обратите внимание, что это вернет абсолютный путь к файлу.
Предполагая, что имя файла 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]
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])