Есть программа, которые берет данные из файла. При запуске программы в консоле требуется ввести имя файла(файл лежит в одной папке с программой). Но при вводе имени выдает ошибку, что такого файла в папке нет. Это решается вводом полного пути до файла (C:\Users....file.dat). Как можно сделать чтобы требовался ввод только имени файла, без пути. (файл лежит в одной папке с программой)
1 Answers
import sys
import os
вариант с указанием полного пути:
full_path = os.path.join(os.path.dirname(os.path.abspath(__file__)), filename)
или
full_path = os.path.join(os.path.dirname(os.path.abspath(sys.argv[0])), filename)
вариант с указанием относительного пути:
full_path = os.path.join(os.path.dirname(__file__), filename)
или
full_path = os.path.join(os.path.dirname(sys.argv[0]), filename)
или для Python 3.4+:
from pathlib import Path
full_path = Path(sys.argv[0]).parent.joinpath('my_file.txt')
или
full_path = Path(__file__).parent.joinpath('my_file.txt')
или (спасибо @insolor за подсказку):
full_path = Path(sys.argv[0]).parent / 'my_file.txt'
если нужен полный (абсолютный) путь:
full_path = Path(sys.argv[0]).parent.absolute() / 'my_file.txt'
UPDATE: отличия __file__ и sys.argv[0]:
__file__ - атрибут, указывающий относительный путь к текущему загруженному модулю/скрипту.
sys.argv[0] - относительный путь к главному скрипту, запущенному в OS.
Пример - создадим два файла:
my1.py (модуль который будет импортироваться из основного модуля):
import sys
print('my1.py\t__file__:\t{}'.format(__file__))
print('my1.py\tsys.argv[0]:\t{}'.format(sys.argv[0]))
m2.py (основной скрипт, который мы запускаем):
import sys
import my1
print('my2.py\t__file__:\t{}'.format(__file__))
print('my2.py\tsys.argv[0]:\t{}'.format(sys.argv[0]))
Вывод скрипта m2.py:
my1.py __file__: D:\temp\aaa\my1.py
my1.py sys.argv[0]: my2.py
my2.py __file__: my2.py
my2.py sys.argv[0]: my2.py
Вывод: если использовать __file__ в функциях из импортированных модулей, то мы получим имя данного модуля, а не главного скрипта ...
UPDATE 2: бывают случаи когда укзанные выше методы будут работать не совсем правильно - посмотрите следующие связанные вопросы/ответы:
- 149,321
- 12
- 59
- 132
-
-
А также в чём разница между
sys.argv[0]и__file__и зачем вы предлагаете оба – andreymal Oct 07 '17 at 10:07 -
1Вместо
joinpathможно сделатьPath(sys.argv[0]).parent / 'my_file.txt'– insolor Oct 07 '17 at 10:26 -
-
-
это может сломаться для программы из архива, для скрипта, запущенного через symlink, или через
execfile(). Посмотрите раздел: Директория со скриптом – jfs Oct 07 '17 at 15:17 -
-
Я упомянул три случая. Если не знаете, то попробуйте и убедитесь в каких именно случаях предложенные вами решения не работают. Упомянутые мной случаи совершенно не обязательно поддерживать, если вы понимаете когда решения могут сломаться. – jfs Oct 07 '17 at 15:22
-
@jfs, спасибо, попробую когда будет больше времени. А что вы имели ввиду под "для программы из архива"? – MaxU - stand with Ukraine Oct 07 '17 at 15:24
-
-
@jfs, хммм, спасибо - про запуск из архивов не знал... – MaxU - stand with Ukraine Oct 07 '17 at 15:36
-
Это говорит, что вы не пытались на ссылку «ваш пакет упакован в архив» нажать в моём ответе :) – jfs Oct 07 '17 at 15:40
script_dir = os.path.dirname(file) abs_file_path = os.path.join(script_dir, fileName) lines = open(abs_file_path).readlines()
– alx Oct 07 '17 at 10:02execfile()(в debugger, IDE, grade tool). – jfs Oct 07 '17 at 15:13