---
name: to_csv
kind: function
lang: py
domain: core
version: "1.0.0"
purity: pure
signature: "to_csv(rows: list[dict], columns: list[str] | None = None, delimiter: str = ',', include_header: bool = True) -> str"
description: "Serializa datos tabulares a CSV. Si columns es None, usa las keys de la primera fila. Escapa campos con comillas, newlines y delimiters correctamente (RFC 4180). Sin dependencias externas."
tags: [csv, serialization, export, tabular, format]
uses_functions: []
uses_types: []
returns: []
returns_optional: false
error_type: ""
imports: []
params:
  - name: rows
    desc: "Lista de diccionarios a serializar como CSV"
  - name: columns
    desc: "Lista opcional de nombres de columnas (orden y filtrado)"
  - name: delimiter
    desc: "Carácter delimitador para campos"
  - name: include_header
    desc: "Si True, incluye fila de encabezados"
output: "String con datos en formato CSV válido (RFC 4180)"
tested: true
tests:
  - "lista simple csv con header"
  - "campos con comas comillas newlines"
  - "columns explicitas reordena y filtra"
  - "include header false"
  - "lista vacia retorna string vacio"
  - "valores none campo vacio"
test_file_path: "python/functions/core/to_csv_test.py"
file_path: "python/functions/core/to_csv.py"
---

## Ejemplo

```python
rows = [{"nombre": "Ana", "edad": 30}, {"nombre": "Bob", "edad": 25}]
csv = to_csv(rows)
# "nombre,edad\r\nAna,30\r\nBob,25"

# Con columnas especificas
csv = to_csv(rows, columns=["edad", "nombre"])
# "edad,nombre\r\n30,Ana\r\n25,Bob"

# Sin header
csv = to_csv(rows, include_header=False)
# "Ana,30\r\nBob,25"
```

## Notas

Implementacion manual sin el modulo csv de stdlib para control total del escaping.
Cumple RFC 4180: escapa con comillas dobles cualquier campo que contenga el delimiter, comillas o saltos de linea. Los valores None se serializan como campo vacio.
