如何在Python中获取类的文件路径?

133
给定一个在Python中的类C,我如何确定该类是在哪个文件中定义的?我需要一些可以从类C或C的实例中工作的东西。
我这样做是因为我通常喜欢将属于同一组的文件放在同一个文件夹中。我想创建一个使用Django模板将自身呈现为HTML的类。基本实现应根据类定义所在的文件名推断模板的文件名。
假设我将一个名为LocationArtifact的类放在文件“base/artifacts.py”中,那么我希望默认行为是模板名称为“base/LocationArtifact.html”。

1
重复:https://dev59.com/7nVC5IYBdhLWcg3whBaj,https://dev59.com/2nRB5IYBdhLWcg3wgHar - S.Lott
3
这些假设你知道你要查找文件的模块,而我只有模块字符串,因为我是在类的实现中工作。 - Staale
这个回答解决了你的问题吗?如何找到Python模块源代码的位置? - mkrieger1
4个回答

181
你可以使用inspect模块,例如这样:
import inspect
inspect.getfile(C.__class__)

1
不确定我做了什么不同,但我必须使用:inspect.getmodule(C.__class__),而不是getfile - AJP
6
注意:不适用于用户创建的类。 - Daniel Braun
12
这可能应该是inspect.getfile(C)。如果C是一个类,那么C.__class__指的是object,这会引发异常 TypeError: <module 'builtins' (built-in)> is a built-in class。我认为只有在实例化后的对象c中,你才需要使用inspect.getfile(c.__class__) - cheshirekow
4
对于扩展抽象基类(metaclass=abc.ABCMeta)的类来说,这样做是行不通的,因为它返回的是/usr/local/lib/python3.7/abc.py而不是适当的文件。以下@JarretHardie提出的解决方案效果更好。 - martian111
被接受的答案:保证是错误的答案。这已经成为 StackOverflow 的传统了。 - Cecil Curry

50

尝试:

import sys, os
os.path.abspath(sys.modules[LocationArtifact.__module__].__file__)

3
要按照OP所需的方式获取C类实例的路径,需要将LocationArtifact替换为obj.__class__,其中objLocationArtifact类的一个实例。 - martian111
1
这对于元类也适用! - Vidar
1
检查占用了很多资源,这是完美的。 - Micah
1
这是正确的方式。在生产代码中,应该通常避免使用inspect。它运行速度慢,容易出错,并且在常见边界情况下会失败。如果你不能写出一行代码来完成它,那么你可能不应该这样做。 - Cecil Curry

5

这种方法对于Django来说是错误的,而且非常强制。

典型的Django应用程序模式如下:

  • /project
    • /appname
      • models.py
      • views.py
      • /templates
        • index.html
        • 等等。

1
+1:做像Django自然而然做的那样,生活会变得更简单。 - S.Lott
1
同意。Django是最少“魔法”的框架之一,但模板、模板标签和应用程序作为其模式的一部分具有某些期望。如果你不得不进行奇怪的类推断,那么你可能走错了方向。 - Soviut

-1
您可以使用错误来获取您的类的路径。
import os
import traceback
class C:
  def getClassPath(self):
    #get foldet path
    try:
        raise ValueError("Example error")
    except Exception as e:
        tb = traceback.extract_tb(e.__traceback__)
       
        return os.path.dirname(tb[-1].filename)
c = C()
print('path is',c.getClassPath())

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接