简体   繁体   中英

Python 3 - Issue importing module - from Parent Directory - that contains File Descriptor

I am unable to do what I believe should be a simple import of a python3 module from a file's parent directory. I can get the module import to work from a parent directory without issue until I introduce a file descriptor into the file that is to be imported.

Example # 1 below is a 'works fine' scenario and # 2 is the problematic scenario that I'm hoping for suggestions on.

#1 - Works fine

App Directory structure:

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

File contents:

# 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'

Run it:

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

#2 - Does not work / Fails

App Directory structure:

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

File contents:

# 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

Run it:

$ 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'

What am I doing wrong here? And please note that foo.txt does in fact exist in the parent directory despite the "FileNotFoundError" error message.

$ cat ../foo.txt
bar

Thanks.

What am I doing wrong here?

You are using a relative path. This:

open("foo.txt")

will lookup foo.txt in the current working directory , whatever it is at this exact moment (which means that it can be just anything and that you should NEVER assume anything about it).

And please note that foo.txt does in fact exist in the parent directory despite the "FileNotFoundError" error message.

Yes, it exists in the parent directory, but not in the current directory.

The canonical solution here is to rebuild the proper path using os.path functions and the __file__ magic variable:

# 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()

Now you can safely call config.read_foo() from any other module, whatever the current working directory is.

As a side note: reading a file in a class statement block is possibly not a great idea - not that it's illegal in Python but it's really a design smell...

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

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