First, assume the following directory structure of a Python package titled mypackage
, which follows the instructions of the guide How To Package Your Python Code:
mypackage/
mypackage/mypackage/
mypackage/mypackage/__init__.py
mypackage/mypackage/a_function.py
mypackage/scripts/
mypackage/scripts/a_script.py
mypackage/tests/
mypackage/tests/a_function_test.py
mypackage/misc/
mypackage/misc/input.txt
# mypackage/misc/actual_output.txt ## Not yet generated!
mypackage/misc/expected_output.txt
mypackage/setup.py
Second, assume that the script a_script.py
imports a_function.py
, reads the file input.txt
, manipulates the content of input.txt
and saves the latter as actual_output.txt
into mypackage/misc/
.
Third, assume that the unittest module mypackage/misc/
contains a test function to compare expected_output.txt
to actual_output.txt
via self.assertMultiLineEqual(expected, actual)
.
Finally, assume that I would like to run the unittest module via python2 setup.py test
.
How do I specify the location of actual_output.txt
and expected_output.txt
in a_function_test.py
without hardcoding their absolute filepaths (and, hence, preventing any transferability of my package)?
Consideration:
I can theoretically hardcode the within-package path to each of the two input files. However, how does the Python interpreter know where to look for mypackage
if it is not yet installed to site-packages
? I had the following idea, but it fails as mypackage
is not yet known:
base_path = os.path.split(inspect.getfile(mypackage))[0]
within_path = mypackage/misc/
expected = open(base_path + within_path + expected_output.txt).read()
actual = open(base_path + within_path + actual_output.txt).read()
self.assertMultiLineEqual(expected, actual)
From a_script.py
you can get to the main mypackage
like so:
mypackage_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
or:
mypackage_dir = os.path.dirname(os.path.abspath(__package__))
then, the other paths can be built, since you know the name of the subpackages:
misc_dir = os.path.join(mypackage_dir, 'misc')
tests_dir = os.path.join(mypackage_dir, 'tests')