Câu trả lời:
Bạn có thể sử dụng __file__
để có được tên của tập tin hiện tại. Khi được sử dụng trong mô-đun chính, đây là tên của tập lệnh ban đầu được gọi.
Nếu bạn muốn bỏ qua phần thư mục (có thể có mặt), bạn có thể sử dụng os.path.basename(__file__)
.
__file__
không được định nghĩa trong trình thông dịch tương tác, vì nó vô nghĩa ở đó. Nó được thiết lập bởi việc thực hiện nhập, vì vậy nếu bạn sử dụng cơ chế nhập không chuẩn thì nó cũng có thể không được đặt.
import os
cần phải có để nó hoạt động. Tôi sẽ thêm điều này vào câu trả lời.
import os
và import os.path
hoàn toàn tương đương.
import sys
print sys.argv[0]
Điều này sẽ in foo.py
cho python foo.py
, dir/foo.py
cho python dir/foo.py
, vv Đó là đối số đầu tiên python
. (Lưu ý rằng sau py2exe thì sẽ như vậy foo.exe
.)
python linkfile.py
, nơi linkfile.py
một symlink đến realfile.py
, sys.argv[0]
sẽ là 'linkfile.py'
, có thể hoặc không thể là những gì bạn muốn; nó chắc chắn là những gì tôi mong đợi . __file__
là như nhau: nó sẽ được linkfile.py
. Nếu bạn muốn tìm 'realfile.py'
từ 'linkfile.py'
, hãy thử os.path.realpath('linkfile.py')
.
__file__
thay thế.
Để hoàn thiện, tôi nghĩ rằng sẽ rất đáng để tóm tắt các kết quả có thể khác nhau và cung cấp tài liệu tham khảo cho hành vi chính xác của từng:
__file__
là tập tin hiện đang thực thi, như chi tiết trong tài liệu chính thức :
__file__
là tên đường dẫn của tệp mà mô-đun được tải, nếu nó được tải từ một tệp. Các__file__
thuộc tính có thể thiếu cho một số loại mô-đun, chẳng hạn như C module được liên kết tĩnh thành người phiên dịch; đối với các mô-đun mở rộng được tải động từ thư viện dùng chung, đó là tên đường dẫn của tệp thư viện dùng chung.
Từ Python3.4 trở đi, mỗi vấn đề 18416 , __file__
luôn là một đường dẫn tuyệt đối, trừ khi tệp hiện đang thực thi là một tập lệnh được thực thi trực tiếp (không thông qua trình thông dịch với -m
tùy chọn dòng lệnh) bằng cách sử dụng đường dẫn tương đối.
__main__.__file__
(yêu cầu nhập __main__
) chỉ cần truy cập vào __file__
thuộc tính đã nói ở trên của mô-đun chính , ví dụ: tập lệnh được gọi từ dòng lệnh.
sys.argv[0]
(yêu cầu nhập sys
) là tên tập lệnh được gọi từ dòng lệnh và có thể là một đường dẫn tuyệt đối, như được nêu chi tiết trong tài liệu chính thức :
argv[0]
là tên tập lệnh (nó phụ thuộc vào hệ điều hành cho dù đây có phải là tên đường dẫn đầy đủ hay không). Nếu lệnh được thực thi bằng-c
tùy chọn dòng lệnh cho trình thông dịch,argv[0]
được đặt thành chuỗi'-c'
. Nếu không có tên tập lệnh nào được chuyển đến trình thông dịch Python, thì đóargv[0]
là chuỗi rỗng.
Như đã đề cập trong câu trả lời khác cho câu hỏi này , các tập lệnh Python được chuyển đổi thành các chương trình thực thi độc lập thông qua các công cụ như py2exe hoặc PyInstaller có thể không hiển thị kết quả mong muốn khi sử dụng phương pháp này (nghĩa là sys.argv[0]
sẽ giữ tên của tệp thực thi thay vì tên của tệp Python chính trong tệp thực thi đó).
Nếu không có tùy chọn nào nói trên có vẻ hoạt động, có thể do hoạt động nhập không đều, mô-đun kiểm tra có thể hữu ích. Cụ thể, việc gọi inspect.getfile(...)
vào inspect.currentframe()
có thể hoạt động, mặc dù cái sau sẽ trở lạiNone
khi chạy trong một triển khai không có khung ngăn xếp Python .
Nếu tập lệnh hiện tại là một liên kết tượng trưng, thì tất cả các đoạn trên sẽ trả về đường dẫn của liên kết tượng trưng thay vì đường dẫn của tệp thực và os.path.realpath(...)
nên được gọi để trích xuất đoạn sau.
os.path.basename(...)
có thể được gọi trên bất kỳ mục nào ở trên để trích xuất tên tệp thực tế và os.path.splitext(...)
có thể được gọi trên tên tệp thực tế để cắt bớt hậu tố của nó, như trongos.path.splitext(os.path.basename(...))
.
Từ Python 3.4 trở đi, trên mỗi PEP 428 , PurePath
lớp của pathlib
mô-đun cũng có thể được sử dụng cho bất kỳ mục nào ở trên. Cụ thể, pathlib.PurePath(...).name
trích xuất tên tệp thực tế và pathlib.PurePath(...).stem
trích xuất tên tệp thực tế mà không có hậu tố của nó.
Lưu ý rằng __file__
sẽ cung cấp cho tệp nơi mã này cư trú, có thể được nhập và khác với tệp chính đang được diễn giải. Để lấy tệp chính, mô-đun __main__ đặc biệt có thể được sử dụng:
import __main__ as main
print(main.__file__)
Lưu ý rằng nó __main__.__file__
hoạt động trong Python 2.7 nhưng không phải trong 3.2, vì vậy hãy sử dụng cú pháp nhập như dưới đây để làm cho nó di động.
rPython
gói từ R
ngôn ngữ. Đó phải là một trường hợp đặc biệt mà quá khó để xử lý.
__main__
nội bộ, để sử dụng trong việc chuyển các biến giữa R
và python
vì vậy sẽ tương đối dễ dàng để đặt nó __main__.__file__
trước khi gọi bất cứ thứ gì khác, nhưng tôi thậm chí không chắc giá trị nào phù hợp trong trường hợp này.
Các câu trả lời trên là tốt. Nhưng tôi thấy phương pháp này hiệu quả hơn bằng cách sử dụng các kết quả trên.
Điều này dẫn đến tên tập tin thực tế không phải là một đường dẫn.
import sys
import os
file_name = os.path.basename(sys.argv[0])
Đối với các phiên bản Python hiện đại (3,4+), Path(__file__).name
nên có nhiều thành ngữ hơn. Ngoài ra, Path(__file__).stem
cung cấp cho bạn tên tập lệnh mà không cần .py
phần mở rộng.
from pathlib import Path
đầu tiên.
pathlib
được giới thiệu trong Python 3.4, vì vậy nó sẽ hoạt động bắt đầu từ Python 3.4.
Giả sử tên tệp là foo.py
, đoạn dưới đây
import sys
print sys.argv[0][:-3]
hoặc là
import sys
print sys.argv[0][::-1][3:][::-1]
Đối với các phạm vi khác có nhiều ký tự hơn, ví dụ như tên tệp foo.pypy
import sys
print sys.argv[0].split('.')[0]
Nếu bạn muốn trích xuất từ một đường dẫn tuyệt đối
import sys
print sys.argv[0].split('/')[-1].split('.')[0]
sẽ xuất foo
Đối số đầu tiên trong sys sẽ là tên tệp hiện tại để nó hoạt động
import sys
print sys.argv[0] # will print the file name
Nếu bạn đang thực hiện nhập bất thường (ví dụ: đó là tệp tùy chọn), hãy thử:
import inspect
print (inspect.getfile(inspect.currentframe()))
Lưu ý rằng điều này sẽ trả về đường dẫn tuyệt đối đến tập tin.
chúng ta có thể thử điều này để có được tên tập lệnh hiện tại mà không cần gia hạn.
import os
script_name = os.path.splitext(os.path.basename(__file__))[0]
tất cả những câu trả lời là tuyệt vời, nhưng có một số vấn đề Bạn có thể không nhìn thấy ngay từ cái nhìn đầu tiên.
cho phép xác định những gì chúng ta muốn - chúng ta muốn tên của tập lệnh đã được thực thi, không phải tên của mô-đun hiện tại - vì vậy __file__
sẽ chỉ hoạt động nếu nó được sử dụng trong tập lệnh đã thực hiện, không phải trong mô-đun đã nhập.
sys.argv
cũng có vấn đề - nếu chương trình của bạn được gọi bởi pytest thì sao? hay người chạy pydoc? hoặc nếu nó được gọi bởi uwsgi?
và - có một phương pháp thứ ba để có được tên tập lệnh, tôi chưa thấy trong các câu trả lời - Bạn có thể kiểm tra ngăn xếp.
Một vấn đề khác là, Bạn (hoặc một số chương trình khác) có thể can thiệp xung quanh sys.argv
và__main__.__file__
- nó có thể có mặt, nó có thể không. Nó có thể hợp lệ, hoặc không. Ít nhất Bạn có thể kiểm tra xem tập lệnh (kết quả mong muốn) có tồn tại không!
thư viện của tôi bitranox / lib_programname tại github thực hiện chính xác điều đó:
__main__
có__main__.__file__
có__main__.__file__
kết quả hợp lệ (tập lệnh đó có tồn tại không?)bằng cách đó, giải pháp của tôi đang làm việc cho đến nay với setup.py test
, uwsgi
, pytest
, pycharm pytest
, pycharm docrunner (doctest)
, dreampie
,eclipse
cũng có một bài viết blog hay về vấn đề đó từ Dough Hellman, "Xác định tên của một quá trình từ Python"
Giải pháp bẩn nhanh của tôi:
__file__.split('/')[-1:][0]
os.path
để phân chia tên tệp
os.path.abspath(__file__)
sẽ cung cấp cho bạn một đường dẫn tuyệt đối (cũng relpath()
có sẵn).
sys.argv[-1]
sẽ cho bạn một con đường tương đối.
Kể từ Python 3.5, bạn chỉ cần làm:
from pathlib import Path
Path(__file__).stem
Xem thêm tại đây: https://docs.python.org/3.5/l Library / pathlib.html # pathlib.PurePath.stem
Ví dụ: tôi có một tệp trong thư mục người dùng của mình có tên test.py
bên trong:
from pathlib import Path
print(Path(__file__).stem)
print(__file__)
chạy kết quả này:
>>> python3.6 test.py
test
test.py
Exception NameError: NameError("global name '__file__' is not defined",)
"