Search code examples
pythoncommand-line-interfacepython-click

What's required for Python Click script to access it's own module directory?


How do I use a Python Click script anywhere in my home directory, and have my script access configs inside the the module's directory?

Let's say I have a little scriptie called ClickDir and it resides in my home directory ~/bin. Here's the tree for a simple script:

.
├── ClickDir
│   ├── config
│   │   └── helloworld_input.txt
│   ├── __init__.py
│   └── scripts
│       ├── clickscript.py
│       └──  __init__.py
├── HelloWorld_output.txt
└── setup.py

It's a very useless script. It reads a file in config and concatenates this text with an input text file of your choosing. Finally, it writes HelloWorld_output.txt to the same directory as your INPUT file,

Usage: ClickDir [OPTIONS] INPUT

I can call the Click function from anywhere, but Click also looks relative to that directory for config/helloworld_input.txt. And so, the script fails to find the config input,

FileNotFoundError: [Errno 2] No such file or directory: '../config/helloworld_input.txt'

I need to apply this in both Linux and Windows (Anaconda on Win 10)

UPDATE:

import click
import os
dir_path = os.path.dirname(os.path.realpath("config/helloworld_input"))

#@cli.command()
@click.command()
@click.argument('input', type=click.File('rb'))
@click.option('--saveas', default='HelloWorld.txt', type=click.File('wb'))
def inout(input, saveas):
    with open(dir_path + "/helloworld_input") as conf:
        print(conf.read())
    while True:
        chunk = input.read(1024)
        if not chunk:
            break
        saveas.write(chunk)

My script is located here: /home/xtian/Documents.x/Projects/CliTools.d/ClickDir/scripts

I backed up a few directories, and ran the script from Projects, but unfortunately the solution described below just calls from the call directory--same as before: FileNotFoundError: [Errno 2] No such file or directory: '/home/xtian/Documents.x/Projects/config/helloworld_input'


Solution

  • You can use __file__ pseudo variable, to find the directory where your script is located.

    dir_path = os.path.dirname(os.path.realpath(__file__))

    Then you can use os.path.join to compose full paths of your data files