2016-11-04 8 views
8

Скажем, у меня есть питон проект, который структурирован следующим образом:Чтение файла с помощью относительный путь в питона проекта

project 
    /data 
     test.csv 
    /package 
     __init__.py 
     module.py 
    main.py 

__init__.py:

from .module import test 

module.py:

import csv 

with open("..data/test.csv") as f: 
    test = [line for line in csv.reader(f)] 

main.py:

import package 

print(package.test) 

Когда я бегу main.py я получаю следующее сообщение об ошибке:

C:\Users\Patrick\Desktop\project>python main.py 
Traceback (most recent call last): 
    File "main.py", line 1, in <module> 
    import package 
    File "C:\Users\Patrick\Desktop\project\package\__init__.py", line 1, in <module> 
    from .module import test 
    File "C:\Users\Patrick\Desktop\project\package\module.py", line 3, in <module> 
    with open("../data/test.csv") as f: 
FileNotFoundError: [Errno 2] No such file or directory: '../data/test.csv' 

Однако, если я бегу module.py из каталога package я не получаю никаких ошибок. Таким образом, кажется, что относительный путь, используемый в open(...), относится только к тому, где выполняется исходный файл (например, __name__ == "__main__")? Я не хочу использовать абсолютные пути. Каковы некоторые способы борьбы с этим?

+1

В качестве побочного элемента, цитирующегося из PEP8: _ «Относительный импорт для внутрипакетов ввозится с большим разочарованием. Всегда используйте абсолютный путь пакета для всех импортов. "_ Здесь,' from package.module import test'. – spectras

ответ

16

Относительные пути относительно current working directory. Если вы не хотите, чтобы ваш путь был, он должен быть абсолютным.

Но есть часто используется трюк, чтобы построить абсолютный путь от текущего сценария: использовать его __file__ специальный атрибут:

import csv 
import os.path 

my_path = os.path.abspath(os.path.dirname(__file__)) 
path = os.path.join(my_path, "../data/test.csv") 
with open(path) as f: 
    test = list(csv.reader(f)) 

Note, из питона 3.4 __file__ всегда абсолютно для импортируемых модулей и вы можете упасть часть os.path.abspath в этом примере. Не то, чтобы это было строго необходимо, но это позволяет избежать неожиданностей, если вы измените текущий рабочий каталог в какой-то момент, и ваш модуль был импортирован с использованием относительного пути.