ENVIRONMENT = config('ENVIRONMENT') # lookups APP_ENVIRONMENT, raises KeyError as variable is not defined
```
+## Custom encoding for environment files
+
+By default, Starlette reads environment files using UTF-8 encoding.
+You can specify a different encoding by setting `encoding` argument.
+
+```python title="myproject/settings.py"
+from starlette.config import Config
+
+# Using custom encoding for .env file
+config = Config(".env", encoding="latin-1")
+```
+
## A full example
Structuring large applications can be complex. You need proper separation of
env_file: str | Path | None = None,
environ: Mapping[str, str] = environ,
env_prefix: str = "",
+ encoding: str = "utf-8",
) -> None:
self.environ = environ
self.env_prefix = env_prefix
if not os.path.isfile(env_file):
warnings.warn(f"Config file '{env_file}' not found.")
else:
- self.file_values = self._read_file(env_file)
+ self.file_values = self._read_file(env_file, encoding)
@overload
def __call__(self, key: str, *, default: None) -> str | None: ...
return self._perform_cast(key, default, cast)
raise KeyError(f"Config '{key}' is missing, and has no default.")
- def _read_file(self, file_name: str | Path) -> dict[str, str]:
+ def _read_file(self, file_name: str | Path, encoding: str) -> dict[str, str]:
file_values: dict[str, str] = {}
- with open(file_name) as input_file:
+ with open(file_name, encoding=encoding) as input_file:
for line in input_file.readlines():
line = line.strip()
if "=" in line and not line.startswith("#"):
with pytest.raises(KeyError):
config.get("ENVIRONMENT")
+
+
+def test_config_with_encoding(tmpdir: Path) -> None:
+ path = tmpdir / ".env"
+ path.write_text("MESSAGE=Hello 世界\n", encoding="utf-8")
+ config = Config(path, encoding="utf-8")
+ assert config.get("MESSAGE") == "Hello 世界"