【问题标题】:Get Path of File Relative Path of File that Imported Module in Python获取Python中导入模块的文件相对路径的文件路径
【发布时间】:2023-04-03 02:45:01
【问题描述】:

我在my_program.py中有这个代码:

from my_module import do_stuff_with_file

do_stuff_with_file("hi.txt")

这是my_module.py:

def do_stuff_with_file(fileName):
    print(fileName)
    # do stuff with the file

当my_module.py 与my_program.py 不在同一目录中时,会出现文件未找到错误。使用此代码 (my_module.py) 解决了此问题。

def do_stuff_with_file(fileName):
    fileName = os.path.join(os.path.dirname(sys.modules['__main__'].__file__), fileName)
    print(fileName)
    # do stuff with file

当my_program.py 由不同目录中的文件导入时会出现问题。

我该如何解决这个问题?

【问题讨论】:

  • 问题不清楚。您能否重申观察到的行为和所需的输出?
  • @Lenormju,我试图澄清这个问题:)。如果您需要示例,请查看 github.com/kethan1/playsound2,并使用 pytest 运行测试
  • 这是与您的项目一起交付的文件是否应该与模块相关,或者此代码是否应该与任何地方的任何文件一起使用?由于my_program.py 使用了相对路径名,因此它相对于os.getcwd() 所说的任何内容都是当前路径。如果从命令行运行,则它是 shells 当前目录。否则它...,好吧,谁知道呢?
  • do_stuff_with_file 会尝试修复相对路径名,这很奇怪。它不应该与任何东西一起使用吗?您可能想要在my_program.py 中进行任何路径操作。我们需要知道您希望此文件在哪里。
  • @tdelaney my_module.py 可能位于my_program.py 的子目录或父目录中。修复路径可以解决这个问题(使用sys.modules['__main__'].__file__)。例如,当使用 pytest 运行(或从另一个 python 文件导入my_program.py)时,就会出现问题。

标签: python import module filepath


【解决方案1】:

给定以下文件层次结构:

stack_overflow/
├─ q67993523/
   ├─ my_module/
   │  ├─ __init__.py
   ├─ 67993523.py
   ├─ hi.txt

文件内容如下:

# 67993523.py
from my_module import do_stuff_with_file

do_stuff_with_file("hi.txt")
# my_module/__init__.py
def do_stuff_with_file(filename):
    print(f"{filename!s} content is :")
    with open(filename, "rt") as file:
        print(file.read())

还有文件hi.txt:

Hello !

当我运行C:\path\to\python.exe C:/stack_overflow/q67993523/67993523.py(q67993523 的路径包含在我的PYTHONPATH 中),当前目录为q67993523/ 时,我得到:

hi.txt content is :
Hello !

但如果我将当前目录更改为 q67993523/my_module/ 并执行完全相同的命令,我会得到:

hi.txt content is :
Traceback:
[...]
FileNotFoundError: [Errno 2] No such file or directory: 'hi.txt'

因为相对于当前工作目录q67993523/my_module/ 没有文件hi.txt,所以该文件将是../hi.txt。

我认为你正在做的是XY problem 的一个实例。

您想要实现的是找到一个给定名称而不是位置的文件。这很难做到,容易出错,并且会包含很多hacks。
我不认为这是实际上你想要做的。我想你想做的不是搜索文件,而是使用它们。所以你不应该丢失他们位置的宝贵信息。

例如,在您的主脚本中(我的是67993523.py),您知道该文件就在同一目录中。但是如果你只是发送hi.txt,因为函数不知道调用她的代码的文件位置,它不知道在哪里搜索文件。
而是给出完整的文件位置,即绝对路径。

如果我将主脚本更改为:

# 67993523.py
from pathlib import Path

from my_module import do_stuff_with_file

the_directory_of_this_pyfile = Path(__file__).parent
do_stuff_with_file((the_directory_of_this_pyfile / "hi.txt").absolute())

并在我的当前目录为q67993523/ 的情况下运行它,我得到:

C:\stack_overflow\q67993523\hi.txt content is :
Hello !

当我将当前目录更改为 q67993523/my_module/ 时,我得到了同样的结果:

C:\stack_overflow\q67993523\hi.txt content is :
Hello !

不同之处在于,在您的脚本中,hi.txt 文件名假定您当前的工作目录是 q67993523/。如果你有一个不同的当前工作目录(因为 Pytest,因为在你想要的任何地方运行脚本,......请参阅 @tdelaney 的评论)然后没有 ./hi.txt 文件,所以它会失败。

我鼓励你学习current working directory这个话题 以及如何表达current Python file directory。

【讨论】:

  • 非常感谢您的帮助。我知道我可能无法摆脱相对路径,但使用 pathlib 似乎可行。谢谢!
  • @KetZoomer 主要要了解的是current working directory (相对路径的开始)和绝对路径(从驱动器的根目录开始)之间的关系。相对路径更短,但当 cwd 不受完全控制时会导致问题。因此,我倾向于支持绝对路径,它适用于任何情况。
猜你喜欢
  • 2019-01-27
  • 1970-01-01
  • 1970-01-01
  • 2015-09-25
  • 1970-01-01
  • 2013-01-31
  • 1970-01-01
  • 1970-01-01
  • 2021-12-20
相关资源
最近更新 更多