超簡単なHelper functionの作成 (in Python) 

# はじめに

PythonのHelper functionをパッケージ化し、プロジェクトで使いまわします。その設定の忘備録です。やっとこの辺りまでやれるようになってきました。:) 

:::note info
この記事はPython初心者が作成しています。詳しいライブラリー作成は、[ここ](https://qiita.com/mofumoffy223/items/a461efba5c80acafdbf0)
や[ここ](https://qiita.com/shinichi-takii/items/e90dcf7550ef13b047b5)らを見てください。間違いや推奨等あればコメントを残してください。よろしくお願いします。
:::

## やりたい事
Pythonのプロジェクトで、自分が作ったHelper Function達を

```python
from helpers import display_datastructure
```
という形で呼び出したいです。

## Data Structrue

自分のHelper functionは、Helpersというディレクトリーから呼び出してみます。
```bash
/some_directory/project
│── helpers/  # (パッケージ)
│   ├── __init__.py  # (必須)
│   ├── myhelpers.py　# Helper functions
│── tmp/
│   ├── 1.py  # (テストスクリプト)
│── setup.py  # (For installing helpers/)
```

## Helper Function  (myhelpers.py)

複雑なデータタイプを再帰的に呼び出して、表示します。

```python
'''
Function name: display_structure  

Input: any data structure - dictionary, list, dictionary of dictionary, list of set, etc.
Output: print the data type, structure, and example data

'''

def display_structure(data, indent=0, name="root", max_depth=10):
    """
    Recursively prints the hierarchy of any nested data structure.
    Highlights only the data structure name (Dictionary, List, Set, Tuple) in green.
    """
    if indent > max_depth:
        print(" " * (indent * 4) + "🔻 [Max depth reached]")
        return  # Stop recursion if depth is too high

    prefix = " " * (indent * 4)  # Indentation for hierarchy visualization

    GREEN = "\033[92m"  # ANSI Green for structure names
    RESET = "\033[0m"   # Reset color to default

    if isinstance(data, dict):
        print(f"{prefix}📜 {name} {GREEN}(Dictionary){RESET} [{len(data)} keys]")
        for key, value in data.items():
            display_structure(value, indent + 1, name=key, max_depth=max_depth)
    
    elif isinstance(data, list):
        print(f"{prefix}📦 {name} {GREEN}(List){RESET} [{len(data)} items]")
        if data:
            display_structure(data[0], indent + 1, name="List Item", max_depth=max_depth)  # Show first item
    
    elif isinstance(data, set):
        print(f"{prefix}🧩 {name} {GREEN}(Set){RESET} [{len(data)} items]")
        if data:
            sample = next(iter(data))  # Get a sample value
            print(f"{prefix}    ├── Example Item: {repr(sample)} ({type(sample).__name__})")
    
    elif isinstance(data, tuple):
        print(f"{prefix}🔗 {name} {GREEN}(Tuple){RESET} [{len(data)} items]")
        if data:
            display_structure(data[0], indent + 1, name="Tuple Item", max_depth=max_depth)  # Show structure of first item
    
    else:
        print(f"{prefix}🔹 {name} ({type(data).__name__}): {repr(data)}")

```
上記を作成し、保存します。

## __init.py__

/helperのディレクトリに、__init__.pyを作ります。

```bash
cd <your project> # Your project top directory
> mkdir helpers
> cd helpers
> helpers> touch __init__.py
```

このファイルに次のように編集します。
```python
from .myhelpers import display_structure
```
保存します。

## setup.py

helpersディレクトリと同じ場所に、setup.pyを作成します。

```bash
> cd ..
> pwd <your project> # Your project top directory 
> touch setup.py
> code . 
```
このファイルに次のように編集します。
```python
from setuptools import setup, find_packages

setup(
    name="helpers",
    version="0.1",
    packages=find_packages(),
    install_requires=[],  # Add dependencies here if needed
)
```
保存します。

## PYTHONPATHの設定

setup.pyが保存されているディレクトリパスをPYTHONPATHに入れます。

```bash
# Assume that you use ~./bashrc for your VARIABLES
> echo 'export PYTHONPATH="/any_directory/project_path:$PYTHONPATH"' >> ~./bashrc
> source ~/.bashrc
```

## mambaの設定

mamba を利用しているので、mamba環境で実施します。mamba環境の設定は、他のサイトを参照ください。pipでパッケージ管理されている場合は、pipだけでよいと思います。

```bash
> cd <your project>
> mamba activate <your enviornment>
> mamba install pip 
# Ensure you are in the project dictionary where you have setup.py
python -m pip install -e .
```

## 新しいプログラムコードの作成

プロジェクト配下であれば、どこでも参照できるはずです。

```bash
> cd <your project>
> cd tmp
> touch temp.py
```


```python
from helpers import display_structure

nested_data = {
    "users": [
        {"name": "Alice", "emails": {"work": "alice@enron.com", "personal": "alice123@gmail.com"}},
        {"name": "Bob", "emails": {"work": "bob@enron.com"}},
        {"name": "Charlie", "emails": set(["charlie@enron.com", "charlie@outlook.com"])}
    ]
}

display_structure(nested_data)

```
Jupytor 環境でも表示されました。

もちろん直接パイソンファイルを呼び出しても実行されます。

```bash
temp> python temp.py
```
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/283070/ac955843-6169-4f23-b082-7551b91b9473.png)

## デバッグ
以下のコマンドでインストールされているか確認してください。
```bash
> pip list | grep helpers

# Check system path and ensure that your project dictory where helpers package exists
> python -c "import sys; print(sys.path)"

# Check your PYTHONPATH and source it 
> echo 'export PYTHONPATH="/any_directory/project_path:$PYTHONPATH"' >> ~./bashrc
> source ~/.bashrc
```
また、次のコードを最初に入れてみて、動作するか確認してください。

```python
import sys
sys.path.append("<your "absolute" project path>")  # Manually add helpers directory
from helpers import display_structure
```
動くようであれば、パスがうまく機能していないので、echo $PYTHONPATHでパスを調べてください。

| **問題** | **解決** |
|------------|-------------------|
| `ModuleNotFoundError: No module named 'helpers'` | ✅　pip list \| grep helpers |
| Python isn't detecting `helpers` | ✅ `__init__.py` の内容確認 |
| Import path issue | ✅ `sys.path` を手動で追加、OS上でPYTHONPATHパスを確認し、再度読み込む |


# 終わりに

これでHelper functionを記述し、プロジェクトで使いまわせると思います。

Happy Hacking!!!