Відповіді:
Ви можете використовувати __file__ім'я поточного файлу. При використанні в головному модулі це ім'я сценарію, до якого було викликано спочатку.
Якщо ви хочете опустити частину каталогу (яка може бути присутнім), ви можете використовувати os.path.basename(__file__).
__file__не визначено в інтерактивному перекладачі, тому що там безглуздо. Він встановлюється реалізацією імпорту, тому якщо ви використовуєте нестандартний механізм імпорту, він також може бути відключений.
import osдля цього потрібно працювати. Я додав би це у відповідь.
import osі import os.pathє абсолютно рівнозначними.
import sys
print sys.argv[0]
Це буде надруковано foo.pyдля python foo.py, dir/foo.pyдля python dir/foo.pyтощо. Це перший аргумент python. (Зверніть увагу, що після py2exe це було б foo.exe.)
python linkfile.py, де linkfile.pyє символьне посилання realfile.py, sys.argv[0]буде 'linkfile.py', що може бути або не бути тим, що ви хочете; це, безумовно, те, що я очікую . __file__те саме: буде linkfile.py. Якщо ви хочете знайти 'realfile.py'з 'linkfile.py', спробуйте os.path.realpath('linkfile.py').
__file__замість цього.
Для повноти, я вважав, що варто було б узагальнити різні можливі результати та подати посилання на точну поведінку кожного:
__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 у цьому виконуваному файлі).
Якщо жоден із згаданих вище варіантів не працює, ймовірно, через неправильну операцію імпорту, модуль перевірки може виявитися корисним. Зокрема, виклик inspect.getfile(...)на це inspect.currentframe()може спрацювати, хоча останній повернетьсяNone під час запуску в реалізацію без кадру стека Python .
Якщо поточний скрипт є символічним посиланням, то все вищезазначене повертає шлях символічного посилання, а не шлях реального файлу, і його os.path.realpath(...)слід викликати для вилучення останнього.
os.path.basename(...)може бути викликано будь-яке з перерахованих вище для того, щоб отримати фактичне ім'я файлу, а також os.path.splitext(...)може бути викликано власне ім'я файлу, щоб урізати його суфікс, як у os.path.splitext(os.path.basename(...)).
З Python 3.4 і далі, за PEP 428 , то PurePathклас з pathlibмодуля може бути також використаний на будь-якому із зазначених вище. Зокрема, pathlib.PurePath(...).nameвитягує власне ім'я файлу та pathlib.PurePath(...).stemвитягує власне ім’я файлу без суфіксу.
Зауважте, що __file__буде надано файл, де знаходиться цей код, який можна імпортувати та відрізняти від основного файлу, який інтерпретується. Щоб отримати основний файл, можна використовувати спеціальний модуль __main__ :
import __main__ as main
print(main.__file__)
Зауважте, що __main__.__file__працює в Python 2.7, але не в 3.2, тому використовуйте синтаксис імпорту як вище, щоб зробити його портативним.
rPythonпакунок з Rмови. Це повинен бути винятковий випадок, з яким занадто важко впоратися.
__main__внутрішньо, для використання при передачі змінних між Rі python, тому було б відносно легко зробити його встановленим, __main__.__file__перш ніж викликати що-небудь інше, але я навіть не впевнений, що було б відповідним значенням у цьому випадку.
Наведені вище відповіді хороші. Але я знайшов цей метод більш ефективним, використовуючи вищезазначені результати.
Це призводить до того, що фактичне ім'я файлу сценарію не є шляхом.
import sys
import os
file_name = os.path.basename(sys.argv[0])
Для сучасних версій Python (3.4+) вони Path(__file__).nameповинні бути більш ідіоматичними. Також Path(__file__).stemдає назву сценарію без .pyрозширення.
from pathlib import Pathспочатку.
pathlibбув представлений в Python 3.4, тому він повинен працювати, починаючи з Python 3.4.
Припустимо, що ім'я файлу - foo.pyфрагмент нижче
import sys
print sys.argv[0][:-3]
або
import sys
print sys.argv[0][::-1][3:][::-1]
Що стосується інших розширень з більшою кількістю символів, наприклад, ім'я файлу foo.pypy
import sys
print sys.argv[0].split('.')[0]
Якщо ви хочете витягнути з абсолютного шляху
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
виведе foo
Першим аргументом у sys буде поточне ім'я файлу, тому це спрацює
import sys
print sys.argv[0] # will print the file name
Якщо ви робите незвичний імпорт (наприклад, файл файлів з опціями), спробуйте:
import inspect
print (inspect.getfile(inspect.currentframe()))
Зауважте, що це поверне абсолютний шлях до файлу.
ми можемо спробувати це, щоб отримати поточне ім'я сценарію без розширення.
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
Моє швидке брудне рішення:
__file__.split('/')[-1:][0]
os.pathрозділення назви файлів
os.path.abspath(__file__)дасть вам абсолютний шлях (також relpath()доступний).
sys.argv[-1] дасть вам відносний шлях.
всі відповіді чудові, але є деякі проблеми, які ви можете не побачити з першого погляду.
давайте визначимо, що ми хочемо - ми хочемо, щоб ім'я сценарію, який був виконаний, а не ім'я поточного модуля - так __file__буде працювати лише в тому випадку, якщо він буде використаний у виконаному сценарії, а не в імпортному модулі.
sys.argvтакож сумнівно - що робити, якщо вашу програму викликали pytest? чи підок-бігун? або якщо його називали uwsgi?
і - є третій спосіб отримання імені сценарію, я не бачив у відповідях - Ви можете перевірити стек.
Ще одна проблема полягає в тому, що Ви (або якась інша програма) можете підробляти sys.argvта перешкоджати__main__.__file__ - вона може бути присутнім, а може й ні. Це може бути дійсним, чи ні. Принаймні Ви можете перевірити, чи існує сценарій (бажаний результат)!
моя бібліотека bitranox / lib_programname в github робить саме це:
__main__ присутній__main__.__file__ присутній__main__.__file__ дійсний результат (чи існує цей сценарій?)тим шляхом, моє рішення працює до сих пір з setup.py test, uwsgi, pytest, pycharm pytest, pycharm docrunner (doctest), dreampie,eclipse
також є приємна стаття в блозі про цю проблему від Тіста Хеллмана, "Визначення імені процесу з Python"
З Python 3.5 ви можете просто зробити:
from pathlib import Path
Path(__file__).stem
Детальніше дивіться тут: https://docs.python.org/3.5/library/pathlib.html#pathlib.PurePath.stem
Наприклад, у мене в файлі користувача мій файл, названий test.pyцим всередині:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
запуск цих виходів:
>>> python3.6 test.py
test
test.py
Exception NameError: NameError("global name '__file__' is not defined",)"