Ayarlar ve Ortam Değişkenleri¶
🌐 Yapay Zekâ ve İnsanlar Tarafından Çeviri
Bu çeviri, insanlar tarafından yönlendirilen bir yapay zekâ ile oluşturuldu. 🤝
Orijinal anlamın yanlış anlaşılması ya da kulağa doğal gelmeme gibi hatalar içerebilir. 🤖
Yapay zekâ LLM'ini daha iyi yönlendirmemize yardımcı olarak bu çeviriyi iyileştirebilirsiniz.
Birçok durumda uygulamanızın bazı harici ayarlara veya konfigürasyonlara ihtiyacı olabilir; örneğin secret key'ler, veritabanı kimlik bilgileri, e-posta servisleri için kimlik bilgileri vb.
Bu ayarların çoğu değişkendir (değişebilir); örneğin veritabanı URL'leri. Ayrıca birçoğu hassas olabilir; örneğin secret'lar.
Bu nedenle bunları, uygulama tarafından okunan environment variable'lar ile sağlamak yaygındır.
İpucu
Environment variable'ları anlamak içinEnvironment Variables dokümanını okuyabilirsiniz.
Tipler ve doğrulama¶
Bu environment variable'lar yalnızca metin (string) taşıyabilir; çünkü Python'ın dışındadırlar ve diğer programlarla ve sistemin geri kalanıyla uyumlu olmaları gerekir (hatta Linux, Windows, macOS gibi farklı işletim sistemleriyle de).
Bu da, Python içinde bir environment variable'dan okunan herhangi bir değerinstr olacağı anlamına gelir; farklı bir tipe dönüştürme veya herhangi bir doğrulama işlemi kod içinde yapılmalıdır.
PydanticSettings¶
Neyse ki Pydantic, environment variable'lardan gelen bu ayarları yönetmek içinPydantic: Settings management ile çok iyi bir yardımcı araç sunar.
pydantic-settings'i kurun¶
Önce,virtual environment oluşturduğunuzdan, aktive ettiğinizden emin olun ve ardındanpydantic-settings paketini kurun:
$pipinstallpydantic-settings---> 100%Ayrıcaall extras'ını şu şekilde kurduğunuzda da dahil gelir:
$pipinstall"fastapi[all]"---> 100%Settings nesnesini oluşturun¶
Pydantic'tenBaseSettings import edin ve bir alt sınıf (sub-class) oluşturun; tıpkı bir Pydantic model'inde olduğu gibi.
Pydantic model'lerinde olduğu gibi, type annotation'larla (ve gerekirse default değerlerle) class attribute'ları tanımlarsınız.
Pydantic model'lerinde kullandığınız aynı doğrulama özelliklerini ve araçlarını burada da kullanabilirsiniz; örneğin farklı veri tipleri veField() ile ek doğrulamalar.
fromfastapiimportFastAPIfrompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50settings=Settings()app=FastAPI()@app.get("/info")asyncdefinfo():return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}İpucu
Hızlıca kopyalayıp yapıştırmak istiyorsanız bu örneği kullanmayın; aşağıdaki son örneği kullanın.
Ardından, buSettings sınıfının bir instance'ını oluşturduğunuzda (bu örnektesettings nesnesi), Pydantic environment variable'ları büyük/küçük harfe duyarsız şekilde okur; yani büyük harfliAPP_NAME değişkeni, yine deapp_name attribute'u için okunur.
Sonrasında veriyi dönüştürür ve doğrular. Böylecesettings nesnesini kullandığınızda, tanımladığınız tiplerde verilere sahip olursunuz (örn.items_per_user birint olur).
settings'i kullanın¶
Daha sonra uygulamanızda yenisettings nesnesini kullanabilirsiniz:
fromfastapiimportFastAPIfrompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50settings=Settings()app=FastAPI()@app.get("/info")asyncdefinfo():return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}Server'ı çalıştırın¶
Sonraki adımda server'ı çalıştırırken konfigürasyonları environment variable olarak geçersiniz; örneğinADMIN_EMAIL veAPP_NAME şu şekilde ayarlanabilir:
$ADMIN_EMAIL="deadpool@example.com"APP_NAME="ChimichangApp"fastapirunmain.py<span style="color: green;">INFO</span>: Uvicorn running on http://127.0.0.1:8000 (Press CTRL+C to quit)İpucu
Tek bir komut için birden fazla env var ayarlamak istiyorsanız aralarına boşluk koyun ve hepsini komuttan önce yazın.
Böyleceadmin_email ayarı"deadpool@example.com" olur.
app_name"ChimichangApp" olur.
items_per_user ise default değeri olan50 olarak kalır.
Ayarları başka bir module'de tutma¶
Bigger Applications - Multiple Files bölümünde gördüğünüz gibi, bu ayarları başka bir module dosyasına koyabilirsiniz.
Örneğinconfig.py adında bir dosyanız şu şekilde olabilir:
frompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50settings=Settings()Ve ardından bunumain.py dosyasında kullanabilirsiniz:
fromfastapiimportFastAPIfrom.configimportsettingsapp=FastAPI()@app.get("/info")asyncdefinfo():return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}İpucu
Bigger Applications - Multiple Files bölümünde gördüğünüz gibi, ayrıca bir__init__.py dosyasına da ihtiyacınız olacak.
Dependency içinde ayarlar¶
Bazı durumlarda, her yerde kullanılan global birsettings nesnesi yerine ayarları bir dependency üzerinden sağlamak faydalı olabilir.
Bu özellikle test sırasında çok işe yarar; çünkü bir dependency'yi kendi özel ayarlarınızla override etmek çok kolaydır.
Config dosyası¶
Bir önceki örnekten devam edersek,config.py dosyanız şöyle görünebilir:
frompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
frompydantic_settingsimportBaseSettingsclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50Dikkat edin, artık default bir instancesettings = Settings() oluşturmuyoruz.
Ana uygulama dosyası¶
Şimdi, yeni birconfig.Settings() döndüren bir dependency oluşturuyoruz.
fromfunctoolsimportlru_cachefromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Annotated[Settings,Depends(get_settings)]):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfunctoolsimportlru_cachefromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Settings=Depends(get_settings)):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}İpucu
@lru_cache konusunu birazdan ele alacağız.
Şimdilikget_settings()'in normal bir fonksiyon olduğunu varsayabilirsiniz.
Sonra bunu dependency olarakpath operation function'dan talep edebilir ve ihtiyaç duyduğumuz her yerde kullanabiliriz.
fromfunctoolsimportlru_cachefromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Annotated[Settings,Depends(get_settings)]):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfunctoolsimportlru_cachefromfastapiimportDepends,FastAPIfrom.configimportSettingsapp=FastAPI()@lru_cachedefget_settings():returnSettings()@app.get("/info")asyncdefinfo(settings:Settings=Depends(get_settings)):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}Ayarlar ve test¶
Ardından,get_settings için bir dependency override oluşturarak test sırasında farklı bir settings nesnesi sağlamak çok kolay olur:
fromfastapi.testclientimportTestClientfrom.configimportSettingsfrom.mainimportapp,get_settingsclient=TestClient(app)defget_settings_override():returnSettings(admin_email="testing_admin@example.com")app.dependency_overrides[get_settings]=get_settings_overridedeftest_app():response=client.get("/info")data=response.json()assertdata=={"app_name":"Awesome API","admin_email":"testing_admin@example.com","items_per_user":50,}🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfastapi.testclientimportTestClientfrom.configimportSettingsfrom.mainimportapp,get_settingsclient=TestClient(app)defget_settings_override():returnSettings(admin_email="testing_admin@example.com")app.dependency_overrides[get_settings]=get_settings_overridedeftest_app():response=client.get("/info")data=response.json()assertdata=={"app_name":"Awesome API","admin_email":"testing_admin@example.com","items_per_user":50,}Dependency override içinde, yeniSettings nesnesini oluştururkenadmin_email için yeni bir değer ayarlarız ve sonra bu yeni nesneyi döndürürüz.
Sonrasında bunun kullanıldığını test edebiliriz.
.env dosyası okuma¶
Çok sayıda ayarınız varsa ve bunlar farklı ortamlarda sık sık değişiyorsa, bunları bir dosyaya koyup, sanki environment variable'mış gibi o dosyadan okumak faydalı olabilir.
Bu yaklaşım oldukça yaygındır ve bir adı vardır: Bu environment variable'lar genellikle.env adlı bir dosyaya konur ve bu dosyaya "dotenv" denir.
İpucu
Nokta (.) ile başlayan dosyalar, Linux ve macOS gibi Unix-benzeri sistemlerde gizli dosyadır.
Ancak dotenv dosyasının mutlaka bu dosya adına sahip olması gerekmez.
Pydantic, harici bir kütüphane kullanarak bu tür dosyalardan okuma desteğine sahiptir. Daha fazlası için:Pydantic Settings: Dotenv (.env) support.
İpucu
Bunun çalışması içinpip install python-dotenv yapmanız gerekir.
.env dosyası¶
Şöyle bir.env dosyanız olabilir:
ADMIN_EMAIL="deadpool@example.com"APP_NAME="ChimichangApp"Ayarları.env'den okuyun¶
Ardındanconfig.py dosyanızı şöyle güncelleyin:
frompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50model_config=SettingsConfigDict(env_file=".env")🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
frompydantic_settingsimportBaseSettings,SettingsConfigDictclassSettings(BaseSettings):app_name:str="Awesome API"admin_email:stritems_per_user:int=50model_config=SettingsConfigDict(env_file=".env")İpucu
model_config attribute'u yalnızca Pydantic konfigürasyonu içindir. Daha fazlası içinPydantic: Concepts: Configuration.
Burada, PydanticSettings sınıfınızın içindeenv_file konfigürasyonunu tanımlar ve değer olarak kullanmak istediğimiz dotenv dosyasının dosya adını veririz.
lru_cache ileSettings'i yalnızca bir kez oluşturma¶
Diskten dosya okumak normalde maliyetli (yavaş) bir işlemdir; bu yüzden muhtemelen bunu yalnızca bir kez yapıp aynı settings nesnesini tekrar kullanmak istersiniz. Her request için yeniden okumak istemezsiniz.
Ancak her seferinde şunu yaptığımızda:
Settings()yeni birSettings nesnesi oluşturulur ve oluşturulurken.env dosyasını yeniden okur.
Dependency fonksiyonu sadece şöyle olsaydı:
defget_settings():returnSettings()bu nesneyi her request için oluştururduk ve.env dosyasını her request'te okurduk. ⚠️
Fakat en üstte@lru_cache decorator'ünü kullandığımız içinSettings nesnesi yalnızca bir kez, ilk çağrıldığı anda oluşturulur. ✔️
fromfunctoolsimportlru_cachefromtypingimportAnnotatedfromfastapiimportDepends,FastAPIfrom.importconfigapp=FastAPI()@lru_cachedefget_settings():returnconfig.Settings()@app.get("/info")asyncdefinfo(settings:Annotated[config.Settings,Depends(get_settings)]):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}🤓 Other versions and variants
Tip
Prefer to use theAnnotated version if possible.
fromfunctoolsimportlru_cachefromfastapiimportDepends,FastAPIfrom.importconfigapp=FastAPI()@lru_cachedefget_settings():returnconfig.Settings()@app.get("/info")asyncdefinfo(settings:config.Settings=Depends(get_settings)):return{"app_name":settings.app_name,"admin_email":settings.admin_email,"items_per_user":settings.items_per_user,}Sonraki request'lerde dependency'ler içindenget_settings() çağrıldığında,get_settings()'in iç kodu tekrar çalıştırılıp yeni birSettings nesnesi yaratılmak yerine, ilk çağrıda döndürülen aynı nesne tekrar tekrar döndürülür.
lru_cache Teknik Detayları¶
@lru_cache, decorator olarak uygulandığı fonksiyonu, her seferinde tekrar hesaplamak yerine ilk seferde döndürdüğü değeri döndürecek şekilde değiştirir; yani fonksiyon kodunu her çağrıda yeniden çalıştırmaz.
Bu nedenle altındaki fonksiyon, argüman kombinasyonlarının her biri için bir kez çalıştırılır. Sonra bu argüman kombinasyonlarının her biri için döndürülmüş değerler, fonksiyon aynı argüman kombinasyonuyla çağrıldıkça tekrar tekrar kullanılır.
Örneğin, şöyle bir fonksiyonunuz varsa:
@lru_cachedefsay_hi(name:str,salutation:str="Ms."):returnf"Hello{salutation}{name}"programınız şu şekilde çalışabilir:
sequenceDiagramparticipant code as Codeparticipant function as say_hi()participant execute as Execute function rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Camila") function ->> execute: execute function code execute ->> code: return the result end rect rgba(0, 255, 255, .1) code ->> function: say_hi(name="Camila") function ->> code: return stored result end rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Rick") function ->> execute: execute function code execute ->> code: return the result end rect rgba(0, 255, 0, .1) code ->> function: say_hi(name="Rick", salutation="Mr.") function ->> execute: execute function code execute ->> code: return the result end rect rgba(0, 255, 255, .1) code ->> function: say_hi(name="Rick") function ->> code: return stored result end rect rgba(0, 255, 255, .1) code ->> function: say_hi(name="Camila") function ->> code: return stored result endBizimget_settings() dependency'miz özelinde ise fonksiyon hiç argüman almaz; dolayısıyla her zaman aynı değeri döndürür.
Bu şekilde, neredeyse global bir değişken gibi davranır. Ancak bir dependency fonksiyonu kullandığı için testte kolayca override edebiliriz.
@lru_cache, Python standart kütüphanesinin bir parçası olanfunctools içindedir. Daha fazla bilgi için:Python docs for@lru_cache.
Özet¶
Uygulamanızın ayarlarını veya konfigürasyonlarını yönetmek için, Pydantic model'lerinin tüm gücüyle birlikte Pydantic Settings'i kullanabilirsiniz.
- Dependency kullanarak test etmeyi basitleştirebilirsiniz.
- Bununla
.envdosyalarını kullanabilirsiniz. @lru_cachekullanmak, dotenv dosyasını her request için tekrar tekrar okumayı engellerken, test sırasında override etmenize de izin verir.







