Pagkuha ng lokasyon (landas) ng isang tumatakbo na file sa Python: __file__.

Negosyo

Upang makuha ang lokasyon (landas) ng isang tumatakbo na file ng script sa Python, gamitin ang __file__. Kapaki-pakinabang ito para sa pag-load ng iba pang mga file batay sa lokasyon ng tumatakbo na file.

Hanggang sa Python 3.8, ibabalik ng __file__ ang landas na tinukoy kapag naisagawa ang utos ng python (o utos ng python3 sa ilang mga kapaligiran). Kung ang isang kamag-anak na landas ay tinukoy, ang kaugnay na landas ay ibabalik; kung ang isang ganap na landas ay tinukoy, ang ganap na landas ay ibabalik.

Sa Python 3.9 at mas bago, ang ganap na landas ay ibinalik anuman ang landas na tinukoy sa runtime.

Ang mga sumusunod na nilalaman ay ipinaliwanag.

  • os.getcwd(),__file__
  • Kunin ang pangalan ng file at pangalan ng direktoryo ng kasalukuyang nagpapatupad ng file.
  • Kunin ang absolute path ng file na naisasagawa.
  • Nagbabasa ng iba pang mga file batay sa lokasyon ng kasalukuyang nagpapatupad ng file.
  • Ilipat ang kasalukuyang direktoryo sa direktoryo ng file na naisakatuparan.
  • Ang parehong pagproseso ay maaaring gawin anuman ang kasalukuyang direktoryo sa runtime.

Tingnan ang sumusunod na artikulo para sa impormasyon sa pagkuha at pagbabago ng kasalukuyang direktoryo (gumaganang direktoryo).

Tandaan na ang __file__ ay hindi maaaring gamitin sa Jupyter Notebook (.ipynb).
Ang direktoryo kung saan matatagpuan ang .ipynb ay papatayin bilang kasalukuyang direktoryo, hindi alintana ang direktoryo kung saan nagsimula ang Jupyter Notebook.
Posibleng gumamit ng os.chdir () sa code upang mabago ang kasalukuyang direktoryo.

os.getcwd () at __file__.

Sa Windows, maaari mong gamitin ang dir command sa halip na pwd upang suriin ang kasalukuyang direktoryo.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

Lumikha ng isang Python script file (file_path.py) na may mga sumusunod na nilalaman sa mas mababang antas (data \ src).

import os

print('getcwd:      ', os.getcwd())
print('__file__:    ', __file__)

Patakbuhin ang utos ng python (o utos ng python3 sa ilang mga kapaligiran) na tumutukoy sa landas sa file ng script.

python3 data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     data/src/file_path.py

Ang absolute path sa kasalukuyang direktoryo ay maaaring makuha sa os.getcwd (). Maaari mo ring gamitin ang __file__ upang makuha ang landas na tinukoy ng utos na python3.

Hanggang sa Python 3.8, ang __file__ ay maglalaman ng landas na tinukoy sa utos ng sawa (o python3). Sa halimbawa sa itaas, ang relatibong landas ay naibalik sapagkat ito ay kamag-anak, ngunit ang ganap na landas ay ibinalik kung ito ay ganap.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

python3 /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py

Ang Python 3.9 at sa paglaon ay ibabalik ang ganap na landas sa __file__, hindi alintana ang landas na tinukoy sa utos ng python (o python3).

Sa sumusunod na halimbawa, idaragdag namin ang code sa parehong script file (file_path.py) sa Python 3.7 at patakbuhin ito kaugnay sa direktoryo sa itaas.

Sa Python 3.7, ginagamit ang absolute path. Ang mga resulta ay ipinapakita sa pagtatapos ng seksyong ito.

Kunin ang pangalan ng file at pangalan ng direktoryo ng kasalukuyang nagpapatupad ng file.

Upang makuha ang pangalan ng file at pangalan ng direktoryo ng tumatakbo na file, gamitin ang sumusunod na pagpapaandar sa os.path module ng karaniwang silid-aklatan.

  • os.path.basename()
  • os.path.dirname()
print('basename:    ', os.path.basename(__file__))
print('dirname:     ', os.path.dirname(__file__))

Resulta ng pagpapatupad.

# basename:     file_path.py
# dirname:      data/src

Kunin ang absolute path ng file na naisasagawa.

Kung ang isang kamag-anak na landas ay nakuha sa __file__, maaari itong mai-convert sa isang ganap na landas na may os.path.abspath (). Ang mga direktoryo ay maaari ring makuha bilang ganap na mga landas.

print('abspath:     ', os.path.abspath(__file__))
print('abs dirname: ', os.path.dirname(os.path.abspath(__file__)))

Resulta ng pagpapatupad.

# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

Kung ang isang ganap na landas ay tinukoy sa os.path.abspath (), ibabalik ito tulad ng dati. Samakatuwid, kung ang __file__ ay isang ganap na landas, ang sumusunod ay hindi magiging sanhi ng isang error.

  • os.path.abspath(__file__)

Nagbabasa ng iba pang mga file batay sa lokasyon ng kasalukuyang nagpapatupad ng file.

Kung nais mong basahin ang iba pang mga file batay sa lokasyon (path) ng file na naisasagawa, sumali sa sumusunod na dalawang mga file gamit ang os.path.join ().

  • Ang direktoryo ng file ay naisakatuparan
  • Kamag-anak na landas sa file upang mabasa mula sa tumatakbo na file.

Kung nais mong basahin ang isang file sa parehong direktoryo ng file na iyong pinapatakbo, pagsamahin lamang ang pangalan ng file.

print('[set target path 1]')
target_path_1 = os.path.join(os.path.dirname(__file__), 'target_1.txt')

print('target_path_1: ', target_path_1)

print('read target file:')
with open(target_path_1) as f:
    print(f.read())

Resulta ng pagpapatupad.

# [set target path 1]
# target_path_1:  data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!

Ang mas mataas na antas ay kinakatawan ng “. \”. Maaari mong iwanan ito ngayon, ngunit maaari mong gamitin ang os.path.normpath () upang gawing normal ang landas at alisin ang labis na “. \” At iba pang mga character.

print('[set target path 2]')
target_path_2 = os.path.join(os.path.dirname(__file__), '../dst/target_2.txt')

print('target_path_2: ', target_path_2)
print('normalize    : ', os.path.normpath(target_path_2))

print('read target file:')
with open(target_path_2) as f:
    print(f.read())

Resulta ng pagpapatupad.

# [set target path 2]
# target_path_2:  data/src/../dst/target_2.txt
# normalize    :  data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Ilipat ang kasalukuyang direktoryo sa direktoryo ng file na naisakatuparan.

Gumamit ng os.chdir () upang ilipat ang kasalukuyang direktoryo sa direktoryo ng file na naisakatuparan sa script.

Maaari mong makita na ilipat ito ng os.getcwd ().

print('[change directory]')
os.chdir(os.path.dirname(os.path.abspath(__file__)))
print('getcwd:      ', os.getcwd())

Resulta ng pagpapatupad.

# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

Kapag ang kasalukuyang direktoryo ay inilipat, hindi na kailangan na isama ito sa direktoryo ng tumatakbo na file kapag binabasa ang file. Maaari mo lamang tukuyin ang landas na may kaugnayan sa direktoryo ng tumatakbo na file.

print('[set target path 1 (after chdir)]')
target_path_1 = 'target_1.txt'

print('target_path_1: ', target_path_1)

print('read target file:')
with open(target_path_1) as f:
    print(f.read())

print()
print('[set target path 2 (after chdir)]')
target_path_2 = '../dst/target_2.txt'

print('target_path_2: ', target_path_2)

print('read target file:')
with open(target_path_2) as f:
    print(f.read())

Resulta ng pagpapatupad.

# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Ang parehong pagproseso ay maaaring gawin anuman ang kasalukuyang direktoryo sa runtime.

Tulad ng ipinakita namin, posible na mai-load ang mga file batay sa lokasyon ng file ng script, na independiyente sa kasalukuyang direktoryo sa runtime, gamit ang isa sa mga sumusunod na pamamaraan.

  • Patapusin ang direktoryo ng tumatakbo na file at ang kamag-anak na landas sa file upang mabasa mula sa tumatakbo na file gamit ang os.path.join ().
  • Ilipat ang kasalukuyang direktoryo sa direktoryo ng file na naisakatuparan.

Mas madaling ilipat ang kasalukuyang direktoryo, ngunit syempre, kung nais mong basahin o magsulat ng higit pang mga file pagkatapos nito, kailangan mong isaalang-alang na ang kasalukuyang direktoryo ay inilipat.

Ang mga resulta ng nakaraang mga halimbawa ay naibubuod sa ibaba.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

python3 data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     data/src/file_path.py
# basename:     file_path.py
# dirname:      data/src
# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1]
# target_path_1:  data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2]
# target_path_2:  data/src/../dst/target_2.txt
# normalize    :  data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
# 
# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Ang resulta ng pagtukoy ng ganap na landas ay ang mga sumusunod.

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook

python3 /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook
# __file__:     /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# basename:     file_path.py
# dirname:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1]
# target_path_1:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2]
# target_path_2:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/../dst/target_2.txt
# normalize    :  /Users/mbp/Documents/my-project/python-snippets/notebook/data/dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
# 
# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!

Ang resulta ng paglipat ng kasalukuyang direktoryo sa terminal at pagpapatupad ng parehong script file ay ipinapakita sa ibaba. Maaari mong makita na ang parehong file ay maaaring mabasa kahit na ito ay naisakatuparan mula sa ibang lokasyon.

cd data/src

pwd
# /Users/mbp/Documents/my-project/python-snippets/notebook/data/src

python3 file_path.py
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# __file__:     file_path.py
# basename:     file_path.py
# dirname:      
# abspath:      /Users/mbp/Documents/my-project/python-snippets/notebook/data/src/file_path.py
# abs dirname:  /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2]
# target_path_2:  ../dst/target_2.txt
# normalize    :  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!
# 
# [change directory]
# getcwd:       /Users/mbp/Documents/my-project/python-snippets/notebook/data/src
# 
# [set target path 1 (after chdir)]
# target_path_1:  target_1.txt
# read target file:
# !! This is "target_1.txt" !!
# 
# [set target path 2 (after chdir)]
# target_path_2:  ../dst/target_2.txt
# read target file:
# !! This is "target_2.txt" !!