Что ожидается от скриптового языка:
- умеет работать с файлами (прочитать/записать csv/yaml/json)
 - умеет работать с сетью (отправить http-запрос)
 - сделать какую-то логику
 - не требует установки окружения и компиляции
 - все в одном файле
 
BASH удовлетворяет всему этому, но у него свои проблемы:
- Тяжело прочитать
 - Тяжело отлаживать
 - Тяжело писать нетривиальную логику
 
Казалось бы Python позволяет решить все эти проблемы, но очень быстро на Питоне хочется ставить какие-нибудь пакеты.
Как это сделать поудобнее?
- Ставим 
poetry. - Создаем папку для скрипта: 
mkdir my-script-1 - Инициализируем там poetry: 
cd my-script-1 && poetry init. Или берем готовый файлpyproject.toml: 
[tool.poetry]
package-mode = false
[tool.poetry.dependencies]
python = "^3.12"
pandas = "^2.2.1"
requests = "^2.31.0"
[build-system]
requires = ["poetry-core"]
build-backend = "poetry.core.masonry.api"
- Создаем файл для нашего скрипта: 
touch main.py && chmod +x main.py - Скачиваем зависимости: 
poetry install --no-root(или простоpoetry install, если выставлено свойствоpackage-mode=false) - Заходим в виртуальное окружение (от туда уже можно запускать скрипт): 
poetry shell, или напрямую запускаемpoetry run ./main.py 
Сам скрипт (просто стартовый пример):
#!/usr/bin/env python3
# https://docs.python.org/3/library/dataclasses.html
from dataclasses import dataclass
# https://pandas.pydata.org/
import pandas as pd
# https://requests.readthedocs.io/en/latest/
import requests
from numpy import ndarray
@dataclass
class DocTags:
    id: str
    tags: [str]
def parse_line(values: ndarray) -> [DocTags]:
    assert values.size == 2
    doc_id: str = values[0]
    tags_str: str = values[1]
    tags = list(map(str.strip, tags_str.split(",")))
    return DocTags(doc_id, tags)
def read_file(filename: str) -> [DocTags]:
    data = pd.read_csv(filename, sep="\t", header=None)
    return list(map(parse_line, data.values))
def main():
    docs = read_file("example.tsv")
    for doc in docs:
        with open(f"out/{doc.id}.txt", 'w') as file:
            file.write(str(doc) + "\n")
            response = requests.put(f"https://httpbin.org/anything/{doc.id}", json=doc.tags)
            file.write(f"status_code={response.status_code} json={response.text}\n")
if __name__ == '__main__':
    main()
Естественно, это все открывается в PyCharm: там можно запускать и вставать в отладку.
В итоге, все-таки есть дополнительные шаги, но их не так уж и много.
PS. Домашнее задание: написать то же, но на чистом BASH. У меня получилось 22 строчки, но сложно читаемых и не поддерживаемых. Впрочем, для скриптов это не особо надо. Тем не менее, это заставило задуматься почему изначально все-таки выбрал BASH, а не Python.
PPS. Домашнее задание 2: переписать скрипт так, чтобы внешние библиотеки (pandas и requests не требовались – по идее это должно быть просто). Решение, если писать не хочется.
PPPS. Можно еще то же самое посмотреть на Kotlin (link1, link2), Ruby и других языках.