pythonpycharmpytest

Read same file from src and test in PyCharm


Where do I put a resource file so that it can be accessed from both src and test in PyCharm?

I've got a PyCharm project structured like this:

src
  scrabble
    board.py
    words.txt
test
  scrabble
    test_board.py

board.py contains this line:

with open('words.txt') as file:
    DICTIONARY = set(word.strip() for word in file)

Within test_board.py, which is a pytest file, I have this:

from scrabble.board import *

This works fine if I run board.py, but if I run test_board.py I get:

FileNotFoundError: [Errno 2] No such file or directory: 'words.txt'

Where can I put words.txt so that it can be accessed from either place? What path should I use in board.txt?

Edit: Someone pointed to How do I get the path and name of the python file that is currently executing?, which answers a different but related question. Indeed, if I put

import os
path = os.path.realpath('words.txt')
print(path)

inside board.py, I see different results when I run board.py

/Users/drake/PycharmProjects/algo_f24_solutions/src/scrabble/words.txt

vs when I run the tests in test_board.py:

/Users/drake/PycharmProjects/algo_f24_solutions/test/words.txt

The same code is looking for the same file in different place depending on whence it is run. Yes, I could hard-code the full path, but that wouldn't work if someone cloned this repo on another machine.

My question, clarified: within PyCharm, where can I put the file so that the same code can access it no matter where the code is run?

This is an assignment I'm giving to students, so I'd rather not ask them to reconfigure path settings or anything like that. I want it to work "out of the box".


Solution

  • Inside board.py, don't just open the bare filename "words.txt".

    Instead, use the __file__ variable to get the full pathname of the current python file, and use that to construct the full path to the words.txt file.

    this_directory = os.path.dirname(__file__)
    words_file = os.path.join(this_directory, "words.txt")
    with open(words_file) as file:
        ...
    

    Was this approach not obvious from the duplicate answer?