簡體   English   中英

如何在 Python 中獲取當前執行文件的路徑?

[英]How do I get the path of the current executed file in Python?

這似乎是一個新手問題,但事實並非如此。 一些常見的方法並不適用於所有情況:

sys.argv[0]

這意味着使用path = os.path.abspath(os.path.dirname(sys.argv[0])) ,但是如果您從另一個目錄中的另一個 Python 腳本運行,這將不起作用,這可能發生在現實生活中.

__文件__

這意味着使用path = os.path.abspath(os.path.dirname(__file__)) ,但我發現這不起作用:

  • py2exe沒有__file__屬性,但有一個解決方法
  • 當您使用execute()從 IDLE 運行時,沒有__file__屬性
  • OS X 10.6 在那里我得到NameError: global name '__file__' is not defined

答案不完整的相關問題:

我正在尋找一種通用解決方案,一種適用於上述所有用例的解決方案

更新

這是一個測試用例的結果:

python a.py 的輸出(在 Windows 上)

a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz

b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz

一個.py

#! /usr/bin/env python
import os, sys

print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print

execfile("subdir/b.py")

子目錄/b.py

#! /usr/bin/env python
import os, sys

print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print

C:.
|   a.py
\---subdir
        b.py

您無法直接確定正在執行的主腳本的位置。 畢竟,有時腳本根本不是來自文件。 例如,它可能來自交互式解釋器或僅存儲在內存中的動態生成的代碼。

但是,您可以可靠地確定模塊的位置,因為模塊始終是從文件加載的。 如果您使用以下代碼創建一個模塊並將其放在與主腳本相同的目錄中,則主腳本可以導入該模塊並使用它來定位自身。

some_path/module_locator.py:

def we_are_frozen():
    # All of the modules are built-in to the interpreter, e.g., by py2exe
    return hasattr(sys, "frozen")

def module_path():
    encoding = sys.getfilesystemencoding()
    if we_are_frozen():
        return os.path.dirname(unicode(sys.executable, encoding))
    return os.path.dirname(unicode(__file__, encoding))

some_path/main.py:

import module_locator
my_path = module_locator.module_path()

如果您在不同的目錄中有多個主要腳本,則可能需要多個 module_locator 副本。

當然,如果您的主腳本是由其他一些工具加載的,而這些工具不允許您導入與腳本位於同一位置的模塊,那么您就不走運了。 在這種情況下,您所追求的信息根本不存在於程序中的任何地方。 最好的辦法是向該工具的作者提交錯誤。

首先,你需要從inspectos導入

from inspect import getsourcefile
from os.path import abspath

接下來,無論您想從哪里找到源文件,只需使用

abspath(getsourcefile(lambda:0))

即使在可執行文件中,此解決方案也很健壯

import inspect, os.path

filename = inspect.getframeinfo(inspect.currentframe()).filename
path     = os.path.dirname(os.path.abspath(filename))

我遇到了類似的問題,我認為這可能會解決問題:

def module_path(local_function):
   ''' returns the module path without the use of __file__.  Requires a function defined
   locally in the module.
   from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
   return os.path.abspath(inspect.getsourcefile(local_function))

它適用於常規腳本和空閑狀態。 我只能說給別人試試!

我的典型用法:

from toolbox import module_path
def main():
   pass # Do stuff

global __modpath__
__modpath__ = module_path(main)

現在我使用 __modpath__ 而不是 __file__。

簡短的回答是沒有保證的方法來獲得你想要的信息,但是在實踐中幾乎總是有效的啟發式方法。 您可能會查看如何在 C 中找到可執行文件的位置? . 它從 C 的角度討論了這個問題,但提出的解決方案很容易轉錄到 Python 中。

有關相關信息,請參閱我對從父文件夾導入模塊問題的回答,包括為什么我的回答不使用不可靠的__file__變量。 這個簡單的解決方案應該與不同的操作系統交叉兼容,因為模塊osinspect是 Python 的一部分。

首先,您需要導入inspectos模塊的一部分。

from inspect import getsourcefile
from os.path import abspath

接下來,在 Python 代碼中需要的任何其他地方使用以下行:

abspath(getsourcefile(lambda:0))

這個怎么運作:

從內置模塊os (如下所述)導入abspath工具。

Mac、NT 或 Posix 的操作系統例程取決於我們使用的系統。

然后從內置模塊inspect導入getsourcefile (如下所述)。

從實時 Python 對象中獲取有用信息。

  • abspath(path)返回文件路徑的絕對/完整版本
  • getsourcefile(lambda:0)以某種方式獲取 lambda 函數對象的內部源文件,因此在 Python shell 中返回'<pyshell#nn>'或返回當前正在執行的 Python 代碼的文件路徑。

getsourcefile(lambda:0)的結果使用abspath應確保生成的文件路徑是 Python 文件的完整文件路徑。
這個解釋的解決方案最初基於答案中的代碼如何在 Python 中獲取當前執行文件的路徑? .

您只是調用了:

path = os.path.abspath(os.path.dirname(sys.argv[0]))

代替:

path = os.path.dirname(os.path.abspath(sys.argv[0]))

abspath()為您提供sys.argv[0] (您的代碼所在的文件名abspath()的絕對路徑,而dirname()返回不帶文件名的目錄路徑。

這應該以跨平台的方式解決問題(只要您不使用解釋器或其他東西):

import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))

sys.path[0]是您的調用腳本所在的目錄(它查找該腳本要使用的模塊的第一個位置)。 我們可以從sys.argv[0]的末尾sys.argv[0]文件本身的名稱(這是我對os.path.basename所做的)。 os.path.join只是以跨平台的方式將它們粘在一起。 os.path.realpath只是確保如果我們得到任何與腳本本身名稱不同的符號鏈接,我們仍然會得到腳本的真實名稱。

我沒有 Mac; 所以,我還沒有在一個上測試過。 請讓我知道它是否有效,因為它似乎應該如此。 我使用 Python 3.4 在 Linux (Xubuntu) 中對此進行了測試。 請注意,此問題的許多解決方案在 Mac 上不起作用(因為我聽說__file__在 Mac 上不存在)。

請注意,如果您的腳本是符號鏈接,它將為您提供它鏈接到的文件的路徑(而不是符號鏈接的路徑)。

您可以使用pathlib模塊中的Path

from pathlib import Path

# ...

Path(__file__)

您可以使用對parent調用在路徑中走得更遠:

Path(__file__).parent

只需添加以下內容:

from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)

或者:

from sys import *
print(sys.argv[0])

如果代碼來自一個文件,你可以得到它的全名

sys._getframe().f_code.co_filename

您還可以將函數名稱檢索為f_code.co_name

我的解決辦法是:

import os
print(os.path.dirname(os.path.abspath(__file__)))
import os
current_file_path=os.path.dirname(os.path.realpath('__file__'))

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM