简体   繁体   English

如何让模块访问非 Python 文件

[英]How to Give Module Access to Non-Python File

Suppose I have the following directory structure:假设我有以下目录结构:

lib/
  main.py
  module1/
    __init__.py
    class1.py
    foo.txt

My class1.py file defines a class that has a function that reads the text file.我的class1.py文件定义了一个 class,它有一个读取文本文件的 function。 My main.py creates an object from the class defined in class1.py and attempts to use the function to read the text file in the module1 folder.我的 main.py 从 class1.py 中定义的main.py创建一个class1.py并尝试使用 function 来读取module1文件夹中的文本文件。 However, when I run the main.py file, it says that it can't find the foo.txt file.但是,当我运行 main.py 文件时,它说找不到foo.txt文件。 How do I give main.py access to foo.txt through class1.py ?如何通过class1.py授予main.py访问foo.txt的权限?

When you call class1.py from main.py , your working directory is lib/ (or wherever you called main.py from) and not module1 .当你从main.py调用class1.py时,你的工作目录是lib/ (或者你调用main.py的任何地方)而不是module1

This means that if you want to access foo.txt you need to specify the path from the working directory , not from where the class1.py is located.这意味着如果你想访问foo.txt你需要从工作目录指定路径,而不是从class1.py所在的位置。


Example:例子:

Assuming that you run main.py from directory lib/ :假设您从目录lib/运行main.py

# class1.py

class Foo():

    def read1(self):
        try:
            f = open('foo.txt')
            print("Successfully opened 'foo.txt'.")
            print(f.read())
        except OSError:
            print("Error when trying to read 'foo.txt'.")

    def read2(self):
        try:
            f = open('module1/foo.txt')
            print("Successfully opened 'module1/foo.txt'.")
            print(f.read())
        except OSError:
            print("Error when trying to read 'module1/foo.txt'.")

if __name__ == '__main__':

    foo = Foo()
    foo.read1()
    foo.read2()
# __init__.py

from module1.class1 import Foo
# main.py

from module1 import Foo

foo = Foo()
foo.read1()
foo.read2()
  • If you are inside module1 and run class1.py :如果您在module1内并运行class1.py
Successfully opened 'foo.txt'.
...file contents...

Error when trying to read 'module1/foo.txt'.

As you can see read1 worked and not read2 .如您所见, read1有效,而不是read2

  • If you are in lib/ and call main.py , you'll get:如果你在lib/中并调用main.py ,你会得到:
Error when trying to read 'foo.txt'.
Successfully opened 'module1/foo.txt'.
...file contents...

This time read2() worked and not read1() .这次read2()有效,而不是read1()

Notes:笔记:

  • if you call class1.py directly from lib/module1 then read_file_1() will work instead of read_file_2() .如果您直接从lib/module1 module1 调用class1.py ,那么read_file_1()将代替read_file_2()工作。
  • you can alleviate this issue completely by using absolute paths *您可以通过使用绝对路径完全缓解此问题 *

I like to use the __file__ attribute of the module.我喜欢使用模块的__file__属性。 Since you know where foo.txt is located with respect to class1.py , you can simply use由于您知道foo.txt相对于class1.py的位置,因此您可以简单地使用

# inside class1.py
from pathlib import Path

file = Path(__file__).resolve().parent / 'foo.txt'

This will work always, no matter where you call the script, or what script is the entry point.这将始终有效,无论您在哪里调用脚本,或者入口点是什么脚本。

Reasoning推理

  • Absolute paths should only be used in quick "one time use scripts".绝对路径只能用于快速的“一次性使用脚本”。
  • Running a script should not (in most cases) rely on the fact in which folder the script is ran.运行脚本不应该(在大多数情况下)依赖于脚本在哪个文件夹中运行的事实。
  • Another way would be to have the static resources in a separate folder, and then read the file using relative paths, like above (Using pathlib is very handy).另一种方法是将 static 资源放在单独的文件夹中,然后使用相对路径读取文件,如上(使用 pathlib 非常方便)。

Drawbacks缺点

  • You'll need to find a workaround if you plan to build and executable with pyinstaller or alike, since the __file__ attribute is not anymore pointing to a .py file.如果您计划使用 pyinstaller 或类似工具构建和执行,则需要找到一种解决方法,因为__file__属性不再指向.py文件。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM