Відповіді:
Ви можете використовувати __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",)
"