Cấu hình tệp json python

Quản lý cấu hình tốt sẽ cho phép phần mềm được thực thi trong mọi môi trường mà không cần thay đổi mã. Nó giúp Ops quản lý tất cả các cài đặt phức tạp và nó cung cấp chế độ xem về những gì có thể xảy ra trong quá trình và thậm chí cho phép họ thay đổi hành vi trong thời gian chạy

Cấu hình phổ biến nhất bao gồm thông tin đăng nhập vào cơ sở dữ liệu hoặc dịch vụ bên ngoài, tên máy chủ của máy chủ được triển khai, tham số động, v.v.

Trong bài viết này, tôi muốn chia sẻ với bạn một số phương pháp hay về quản lý cấu hình và cách chúng tôi có thể triển khai chúng trong Python. Nếu các bạn có thêm ý kiến ​​hãy để lại bình luận bên dưới

Khi nào chúng ta cần một tệp cấu hình riêng?

Trước khi viết bất kỳ tệp cấu hình nào, chúng ta nên tự hỏi tại sao chúng ta cần một tệp bên ngoài?

Một bài kiểm tra giấy quỳ để xem liệu một ứng dụng có tất cả cấu hình được xác định chính xác từ mã hay không là liệu cơ sở mã có thể được tạo thành mã nguồn mở bất kỳ lúc nào mà không ảnh hưởng đến bất kỳ thông tin đăng nhập nào hay không. Lưu ý rằng định nghĩa “config” này không bao gồm cấu hình ứng dụng nội bộ, chẳng hạn như config/routes.rb trong Rails hoặc cách các mô-đun mã được kết nối trong Spring. Loại cấu hình này không khác nhau giữa các lần triển khai và do đó, cách tốt nhất là thực hiện trong mã

Nó khuyến nghị rằng mọi tham số phụ thuộc vào môi trường, chẳng hạn như thông tin xác thực cơ sở dữ liệu nên nằm trong tệp bên ngoài. Mặt khác, chúng chỉ là hằng số bình thường trong mã. Một trường hợp sử dụng khác mà tôi thấy rất nhiều là lưu trữ các biến động trong tệp bên ngoài, chẳng hạn như danh sách đen hoặc danh sách trắng. Nhưng nó cũng có thể là một số trong một khoảng nào đó (e. g. hết thời gian) hoặc một số văn bản miễn phí. Các biến này có thể giống nhau trong mỗi môi trường, nhưng tệp cấu hình giúp phần mềm linh hoạt và dễ chỉnh sửa hơn nhiều. Tuy nhiên, nếu nó phát triển quá nhiều, chúng tôi có thể cân nhắc chuyển nó sang cơ sở dữ liệu để thay thế

Tôi nên sử dụng định dạng nào của tệp cấu hình?

Trên thực tế, không có ràng buộc nào về định dạng của tệp cấu hình miễn là mã có thể đọc và phân tích chúng. Nhưng, có một số thực hành tốt

Các định dạng chuẩn và phổ biến nhất là YAML, JSON, TOML và INI. Một file cấu hình tốt phải đáp ứng ít nhất 3 tiêu chí này

  1. Dễ đọc và chỉnh sửa. Nó phải dựa trên văn bản và được cấu trúc theo cách dễ hiểu. Ngay cả những người không phải là nhà phát triển cũng có thể đọc
  2. cho phép bình luận. Tệp cấu hình không phải là thứ sẽ chỉ được đọc bởi các nhà phát triển. Điều cực kỳ quan trọng trong sản xuất khi những người không phải là nhà phát triển cố gắng hiểu quy trình và sửa đổi hành vi của phần mềm. Viết bình luận là một cách để nhanh chóng giải thích một số điều nhất định, do đó làm cho tệp cấu hình trở nên rõ ràng hơn
  3. Dễ triển khai. Tệp cấu hình phải được chấp nhận bởi tất cả các hệ điều hành và môi trường. Nó cũng sẽ dễ dàng được chuyển đến máy chủ thông qua đường dẫn CDaaS

Có thể bạn vẫn chưa biết cái nào tốt hơn. Nhưng nếu bạn nghĩ về nó trong ngữ cảnh của Python, thì câu trả lời sẽ là YAML hoặc INI. YAML và INI được hầu hết các gói và chương trình Python chấp nhận. INI có lẽ là giải pháp đơn giản nhất chỉ với 1 cấp độ của hệ thống phân cấp. Tuy nhiên, không có kiểu dữ liệu trong INI, mọi thứ được mã hóa dưới dạng chuỗi

Cấu hình tương tự trong YAML trông như thế này. Như bạn có thể thấy, YAML hỗ trợ cấu trúc lồng nhau khá tốt (như JSON). Ngoài ra, YAML mã hóa một số loại dữ liệu như chuỗi, số nguyên, kép, boolean, danh sách, từ điển, v.v.

JSON rất giống với YAML và cũng cực kỳ phổ biến, tuy nhiên, không thể thêm nhận xét vào JSON. Tôi sử dụng JSON rất nhiều cho cấu hình bên trong chương trình, nhưng không phải khi tôi muốn chia sẻ cấu hình với người khác

Mặt khác, TOML tương tự như INI, nhưng hỗ trợ nhiều loại dữ liệu hơn và đã xác định cú pháp cho các cấu trúc lồng nhau. Nó được sử dụng rất nhiều bởi các quản lý gói Python như pip hoặc thơ. Nhưng nếu file cấu hình có quá nhiều cấu trúc lồng nhau thì YAML là lựa chọn tốt hơn. Tệp sau đây trông giống như INI, nhưng mọi giá trị chuỗi đều có dấu ngoặc kép

Cho đến nay, tôi đã giải thích TẠI SAO và CÁI GÌ. Trong các phần tiếp theo, tôi sẽ chỉ cho bạn CÁCH

Lựa chọn 1. YAML/JSON — Chỉ cần đọc tệp bên ngoài

Như thường lệ, chúng tôi bắt đầu từ cách tiếp cận cơ bản nhất, đó là tạo một tệp bên ngoài và đọc nó. Python có các gói tích hợp chuyên dụng để phân tích các tệp YAML và JSON. Như bạn thấy từ mã bên dưới, chúng thực sự trả về cùng một đối tượng dict, vì vậy quyền truy cập thuộc tính sẽ giống nhau cho cả hai tệp

Đọc

Do vấn đề bảo mật, nên sử dụng yaml.safe_load() thay vì yaml.load() để tránh tiêm mã vào tệp cấu hình

Thẩm định

Cả hai gói sẽ tăng FileNotFoundError cho một tệp không tồn tại. YAML đưa ra các ngoại lệ khác nhau cho tệp không phải YAML và tệp YAML không hợp lệ, trong khi JSON đưa ra JSONDecoderError cho cả hai lỗi

Lựa chọn 2. Cofigureparser — Gói tích hợp Python

Từ đây trở đi, tôi sẽ giới thiệu các gói được thiết kế để quản lý cấu hình. Chúng tôi bắt đầu với gói tích hợp Python. Configureparser

Configureparser chủ yếu được sử dụng để đọc và ghi các tệp INI, nhưng nó cũng hỗ trợ từ điển và đối tượng tệp lặp lại làm đầu vào. Mỗi tệp INI bao gồm nhiều phần trong đó có nhiều cặp khóa, giá trị. Dưới đây là một ví dụ về việc truy cập các trường

Đọc

Configureparser không đoán kiểu dữ liệu trong tệp cấu hình, vì vậy mọi cấu hình được lưu trữ dưới dạng chuỗi. Nhưng nó cung cấp một số phương thức để chuyển đổi chuỗi thành kiểu dữ liệu chính xác. Điều thú vị nhất là kiểu Boolean vì nó có thể nhận ra các giá trị Boolean từ

# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
0_______0_______1
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
2
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
3
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
4
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
5
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
6
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
7

Như đã đề cập trước đó, nó cũng có thể đọc từ một từ điển bằng cách sử dụng

# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
8 hoặc một chuỗi bằng cách sử dụng
# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False
9 hoặc một đối tượng tệp có thể lặp lại bằng cách sử dụng
python my_app.py db=postgresql schema=school.yaml
0

Thẩm định

Việc xác thực Configureparser không đơn giản như YAML và JSON. Đầu tiên, nó không tăng FileNotFoundError nếu tệp không tồn tại, nhưng thay vào đó, nó tăng KeyError khi nó cố gắng truy cập một khóa

Bên cạnh đó, gói “bỏ qua” lỗi thụt đầu dòng. Giống như ví dụ dưới đây, nếu bạn có thêm một tab hoặc khoảng trắng trước “DEBUG”, thì bạn sẽ nhận được giá trị sai cho cả ENVIRONMENT và DEBUG

Tuy nhiên, Configureparser có thể trả về ParserError cho nhiều lỗi (xem trường hợp thử nghiệm cuối cùng). Điều này giúp chúng tôi giải quyết vấn đề trong một lần

Tùy chọn3. python-dotenv — Đặt cấu hình dưới dạng biến môi trường

Bây giờ chúng tôi chuyển sang thư viện của bên thứ ba. Cho đến nay, tôi thực sự đã bỏ lỡ một loại tệp cấu hình đó là

python my_app.py db=postgresql schema=school.yaml
1. Các biến bên trong tệp
python my_app.py db=postgresql schema=school.yaml
1 sẽ được tải dưới dạng biến môi trường trước
python my_app.py db=postgresql schema=school.yaml
3 và có thể được truy cập bởi
python my_app.py db=postgresql schema=school.yaml
4

Một tệp

python my_app.py db=postgresql schema=school.yaml
1 về cơ bản trông như thế này. Đường dẫn mặc định là thư mục gốc của dự án của bạn

ENVIRONMENT=test
DEBUG=true
USERNAME=xiaoxu
PASSWORD=xiaoxu
HOST=127.0.0.1
PORT=5432

Đọc

thật sự rất dễ dàng để sử dụng. Bạn có thể quyết định xem mình có muốn ghi đè biến hiện có trong môi trường bằng tham số

python my_app.py db=postgresql schema=school.yaml
6 hay không

Thẩm định

Tuy nhiên,

python my_app.py db=postgresql schema=school.yaml
7 không xác thực tệp
python my_app.py db=postgresql schema=school.yaml
1. Nếu bạn có một tệp
python my_app.py db=postgresql schema=school.yaml
1 như thế này và bạn muốn truy cập GỠ LỖI, bạn sẽ nhận được kết quả trả về là Không mà không có ngoại lệ

# .env
ENVIRONMENT=test
DEBUG
# load.py
load_dotenv()
print('DEBUG' in os.environ.keys())
# False

Tùy chọn4. Dynaconf — Cấu hình cài đặt mạnh mẽ cho Python

Dynaconf là một cấu hình cài đặt rất mạnh mẽ cho Python hỗ trợ nhiều định dạng tệp. yaml, json, ini, toml và trăn. Nó có thể tự động tải tệp

python my_app.py db=postgresql schema=school.yaml
1 và hỗ trợ các quy tắc xác thực tùy chỉnh. Tóm lại, nó bao gồm khá nhiều chức năng từ 3 tùy chọn trước đó và thậm chí còn hơn thế nữa. Ví dụ: bạn có thể lưu trữ mật khẩu được mã hóa và sử dụng a để giải mã mật khẩu. Nó cũng được tích hợp độc đáo với Flask, Django và Pytest. Tôi sẽ không đề cập đến tất cả các chức năng trong bài viết này, để biết thêm chi tiết, vui lòng tham khảo tài liệu của họ

Đọc

Dynaconf sử dụng

python my_app.py db=postgresql schema=school.yaml
1 để tìm tất cả tệp cài đặt và điền vào đối tượng
python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
2 các trường. Nếu 2 tệp cài đặt có cùng một biến thì tệp cài đặt mới nhất sẽ ghi đè giá trị

Thẩm định

Một trong những tính năng thú vị đối với tôi là trình xác thực tùy chỉnh. Như đã đề cập trước đây, Configureparser không xác thực tệp INI đủ nghiêm ngặt, nhưng điều này có thể đạt được trong dynaconf. Trong ví dụ này, tôi kiểm tra xem một số khóa có tồn tại trong tệp hay không và liệu một số khóa có đúng giá trị không. Nếu bạn đọc từ tệp YAML hoặc TOML hỗ trợ nhiều kiểu dữ liệu, bạn thậm chí có thể kiểm tra xem một số có nằm trong một phạm vi nhất định hay không

Tích hợp với Pytest

Một tính năng thú vị khác là tích hợp với pytest. Cài đặt cho thử nghiệm đơn vị thường khác với các môi trường khác. Bạn có thể sử dụng

python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
3 để cho phép ứng dụng đọc một phần khác trong tệp cài đặt của bạn hoặc sử dụng
python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
4 để thay thế một cặp khóa và giá trị cụ thể trong tệp cài đặt

Làm mới cấu hình trong thời gian chạy

Dynaconf cũng hỗ trợ

python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
5 , giúp dọn dẹp và thực thi tất cả các trình tải. Điều này hữu ích nếu bạn muốn ứng dụng tải lại tệp cài đặt trong thời gian chạy. Ví dụ: ứng dụng sẽ tự động tải lại cài đặt khi tệp cấu hình được mở và sửa đổi

Tùy chọn5. Hydra- Đơn giản hóa sự phát triển bằng cách tự động tạo cấu hình phân cấp

Tùy chọn cuối cùng không chỉ là một trình tải tệp. Hydra là một khung do Facebook phát triển để định cấu hình các ứng dụng phức tạp một cách trang nhã

Bên cạnh việc đọc, ghi và xác thực các tệp cấu hình, Hydra cũng đưa ra chiến lược đơn giản hóa việc quản lý nhiều tệp cấu hình, ghi đè lên nó thông qua giao diện dòng lệnh, tạo ảnh chụp nhanh của mỗi lần chạy, v.v.

Đọc

Đây là cách sử dụng cơ bản của hydra.

python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
6 có nghĩa là thêm một trường mới trong cấu hình hoặc
python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
7 để ghi đè một trường hiện có

Thẩm định

Hydra tích hợp độc đáo với @dataclass để thực hiện các xác thực cơ bản như kiểm tra loại và các trường chỉ đọc. Nhưng nó không hỗ trợ phương pháp

python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
8 để kiểm tra giá trị nâng cao như được mô tả trong bài viết trước của tôi

nhóm cấu hình

Hydra giới thiệu một khái niệm gọi là nhóm cấu hình. Ý tưởng là nhóm các cấu hình có cùng loại và chọn một trong số chúng trong quá trình thực thi. Ví dụ: bạn có thể có một nhóm “cơ sở dữ liệu” với một cấu hình cho Postgres và một cấu hình khác cho MySQL

Khi nó trở nên phức tạp hơn, bạn có thể có một bố cục như thế này trong chương trình của mình (một ví dụ từ tài liệu của Hydra)

và bạn muốn đánh giá ứng dụng của mình bằng các kết hợp khác nhau của

python my_app.py schema=warehouse,support,school db=mysql,postgresql -m
9,
[2019-10-01 14:44:16,254] - Launching 6 jobs locally
[2019-10-01 14:44:16,254] - Sweep output dir : multirun/2019-10-01/14-44-16
[2019-10-01 14:44:16,254] - #0 : schema=warehouse db=mysql
[2019-10-01 14:44:16,321] - #1 : schema=warehouse db=postgresql
[2019-10-01 14:44:16,390] - #2 : schema=support db=mysql
[2019-10-01 14:44:16,458] - #3 : schema=support db=postgresql
[2019-10-01 14:44:16,527] - #4 : schema=school db=mysql
[2019-10-01 14:44:16,602] - #5 : schema=school db=postgresql
0 và
[2019-10-01 14:44:16,254] - Launching 6 jobs locally
[2019-10-01 14:44:16,254] - Sweep output dir : multirun/2019-10-01/14-44-16
[2019-10-01 14:44:16,254] - #0 : schema=warehouse db=mysql
[2019-10-01 14:44:16,321] - #1 : schema=warehouse db=postgresql
[2019-10-01 14:44:16,390] - #2 : schema=support db=mysql
[2019-10-01 14:44:16,458] - #3 : schema=support db=postgresql
[2019-10-01 14:44:16,527] - #4 : schema=school db=mysql
[2019-10-01 14:44:16,602] - #5 : schema=school db=postgresql
1, sau đó bạn có thể chạy

python my_app.py db=postgresql schema=school.yaml

Hơn …

Hydra hỗ trợ quét tham số với

[2019-10-01 14:44:16,254] - Launching 6 jobs locally
[2019-10-01 14:44:16,254] - Sweep output dir : multirun/2019-10-01/14-44-16
[2019-10-01 14:44:16,254] - #0 : schema=warehouse db=mysql
[2019-10-01 14:44:16,321] - #1 : schema=warehouse db=postgresql
[2019-10-01 14:44:16,390] - #2 : schema=support db=mysql
[2019-10-01 14:44:16,458] - #3 : schema=support db=postgresql
[2019-10-01 14:44:16,527] - #4 : schema=school db=mysql
[2019-10-01 14:44:16,602] - #5 : schema=school db=postgresql
2, chạy nhiều công việc cùng lúc với các tệp cấu hình khác nhau. Chẳng hạn, đối với ví dụ trước, chúng ta có thể chạy

python my_app.py schema=warehouse,support,school db=mysql,postgresql -m

Sau đó, về cơ bản bạn bắt đầu 6 công việc cùng một lúc

[2019-10-01 14:44:16,254] - Launching 6 jobs locally
[2019-10-01 14:44:16,254] - Sweep output dir : multirun/2019-10-01/14-44-16
[2019-10-01 14:44:16,254] - #0 : schema=warehouse db=mysql
[2019-10-01 14:44:16,321] - #1 : schema=warehouse db=postgresql
[2019-10-01 14:44:16,390] - #2 : schema=support db=mysql
[2019-10-01 14:44:16,458] - #3 : schema=support db=postgresql
[2019-10-01 14:44:16,527] - #4 : schema=school db=mysql
[2019-10-01 14:44:16,602] - #5 : schema=school db=postgresql

Phần kết luận

Trong bài viết này, tôi đã nói về quản lý cấu hình trong Python về TẠI SAO, CÁI GÌ và NHƯ THẾ NÀO. Tùy thuộc vào trường hợp sử dụng, một công cụ/khuôn khổ phức tạp không phải lúc nào cũng tốt hơn một gói đơn giản. Cho dù bạn chọn cái nào, bạn phải luôn nghĩ về khả năng đọc, khả năng bảo trì và cách phát hiện lỗi càng sớm càng tốt. Trên thực tế, tệp cấu hình chỉ là một loại mã khác

Làm cách nào để sử dụng tệp JSON cấu hình trong Python?

Sử dụng tệp cấu hình JSON trong Python. .
Bước 1. Tạo tệp cấu hình JSON. Tạo tệp văn bản trống 'config. JSON'.
Bước 2. Tạo tập lệnh Python. Tạo tệp văn bản trống 'loadconfig. py' và đặt nó vào cùng thư mục với 'config. JSON'.
Hành hình. Mở một thiết bị đầu cuối và thực thi tập lệnh với 'python loadconfig. py'

Làm cách nào để viết tệp JSON cấu hình?

Tạo tệp cấu hình JSON theo cách thủ công .
Tạo ứng dụng đặt tên tệp. json
Sử dụng thông tin cấu hình được cung cấp trong ứng dụng. dịch vụ. .
Sử dụng mẫu trong phần Xác định triển khai để chỉ định tất cả các tệp và tài nguyên mà bạn muốn triển khai từ bộ chứa Cloud Storage của mình

JSON có thể được sử dụng cho tệp cấu hình không?

Nhiều dự án sử dụng JSON cho tệp cấu hình . Có lẽ ví dụ rõ ràng nhất là gói. json được sử dụng bởi npm và yarn, nhưng có nhiều tệp khác, bao gồm CloudFormation (ban đầu chỉ có JSON, nhưng hiện cũng hỗ trợ YAML) và trình soạn thảo (PHP).

Việc sử dụng cấu hình JSON là gì?

json là tệp cấu hình chính. Dữ liệu từ cấu hình. json được sử dụng để định cấu hình máy ảo . Sau khi chỉnh sửa tệp, đảm bảo rằng cú pháp JSON của bạn hợp lệ.