Python 3-问题导入模块-从父目录-包含文件描述符

时间:2018-08-20 02:59:28

标签: python python-3.x python-import

我无法执行我认为应该从文件的父目录简单导入python3模块的操作。我可以从父目录获得模块导入功能,而不会出现问题直到。我向要导入的文件中引入了文件描述符。

下面的示例1是一个“运行良好”的方案,而示例2是我希望就此提出建议的有问题的方案。

#1-工作正常

应用目录结构:

├── app
│   └── app.py
├── config.py

文件内容:

# app.py
import sys
sys.path.insert(0, '../')
from config import Config as conf

foo = conf.foo

if __name__ == '__main__':
    print('hello from app main')
    print(f'foo is --> {foo}')


#config.py
class Config():
    foo = 'bar'

运行它:

$ pwd
app/
$ python app.py
hello from app main
foo is --> bar

#2-不起作用/失败

应用目录结构:

├── app
│   └── app.py
├── config.py
└── foo.txt <-- **Introduced new file here**

文件内容:

# app.py
import sys
sys.path.insert(0, '../')
from config import Config as conf

foo = conf.foo

if __name__ == '__main__':
    print('hello from app main')
    print(f'foo is --> {foo}')

# config.py
class Config():
    with open('foo.txt', 'rt') as f:
        foo = f.readline().rstrip()   

# foo.txt
bar

运行它:

$ pwd
app/

$ python app.py
Traceback (most recent call last):
  File "app.py", line 3, in <module>
    from config import Config as conf
  File "../config.py", line 1, in <module>
    class Config():
  File "../config.py", line 2, in Config
    with open('foo.txt', 'rt') as f:
FileNotFoundError: [Errno 2] No such file or directory: 'foo.txt'

我在这里做错了什么?并且请注意,尽管出现了“ FileNotFoundError”错误消息,但foo.txt 确实确实存在于父目录中。

$ cat ../foo.txt
bar

谢谢。

1 个答案:

答案 0 :(得分:1)

  

我在这里做什么错了?

您正在使用相对路径。这个:

open("foo.txt")

将会在current working directory中查找foo.txt,无论在此确切时刻是什么(这意味着它可以是任何东西,并且您永远都不应假设任何事情)。

  

请注意,尽管出现了“ FileNotFoundError”错误消息,但foo.txt实际上存在于父目录中。

是的,它存在于父目录中,但不存在于 current 目录中。

典型的解决方案是使用os.path函数和__file__魔术变量重建正确的路径:

# config.py
import os

def read_foo():
    # build the full path to the current file
    here = os.path.abspath(__file__)
    # extract the directory path
    dirpath = os.path.dirname(here)
    # foo.txt is supposed to be in the same directory:
    foopath = os.path.join(dirpath, "foo.txt")
    with open(foopath) as f:
        return f.readline().rstrip()

现在,无论当前工作目录是什么,您都可以从任何其他模块安全地调用config.read_foo()

作为旁注:在class语句块中读取文件可能不是一个好主意-并不是说它在Python中是非法的,而是一种设计上的味道...