Flask CLI neden Flask.run yerine öneriliyor?


13

Flask 0.11'de bir flaskCLI piyasaya sürüldü. Hem dokümanlar hem de changelog durumu bunun tavsiye edilir.

Geliştirme Sunucusu belgeleri :

Flask 0.11'den başlayarak, bir geliştirme sunucusu çalıştırmanın birden fazla yerleşik yolu vardır. En iyisi flask komut satırı yardımcı programıdır, ancak Flask.run()yöntemi kullanmaya devam edebilirsiniz .

Komut satırı

Şişe o üstün yeniden deneyimi sağlar, çünkü komut satırı komut dosyası (Komut Satırı Arayüzü) kuvvetle nedeniyle bu uygulamayı yükler nasıl gelişmesi için tavsiye edilir. Temel kullanım şöyledir:

$ export FLASK_APP=my_application
$ export FLASK_DEBUG=1
$ flask run

Değişiklik günlüğü :

  • Tıklayın CLI sistemi aracılığıyla yerel hata ayıklama sunucusunu başlatmak flaskiçin flask.climodül eklendi . flask.run()Farklı bir tasarım nedeniyle daha hızlı ve daha güvenilir çalıştığı ve aynı zamanda yerini aldığı için bu eski yöntem üzerinde önerilir Flask-Script.

Şimdiye kadar bu "üstün yeniden yükleme deneyimi" fark etmedi. Özel bir komut dosyası üzerinde CLI kullanma noktasını göremiyorum.

Kullanıyorsanız Flask.run, ben sadece bir python dosyası yazmak istiyorum:

#!/usr/bin/env python3
from my_app import app


if __name__ == '__main__':
    app.run(debug=True)

CLI kullanılıyorsa, ortam değişkenleri belirtilmelidir. CLI belgelerinde bunun activatevirtualenvwrapper komut dosyasına entegre edilebileceği belirtilmektedir . Şahsen ben bu uygulamanın bir parçası olduğunu düşünüyorum ve sürüm kontrolü altında olması gerektiğini düşünüyorum. Ne yazık ki, bir kabuk betiği gereklidir:

#!/usr/bin/env bash
export FLASK_APP=my_app:app
export FLASK_DEBUG=1

flask run

Tabii ki buna, herhangi bir Windows kullanıcısı işbirliği yapmaya başlar başlamaz ek bir bat komut dosyası eşlik edecektir.

Ayrıca ilk seçenek, gerçek uygulamaya başlamadan önce Python'da yazılı kuruluma izin verir.

Bu, örneğin

  • komut satırı bağımsız değişkenlerini Python'da ayrıştırma
  • uygulamayı çalıştırmadan önce günlüğe kaydetmeyi ayarlama

Özel komutlar eklemenin mümkün olduğunu destekliyor gibi görünüyorlar. Bunun neden isteğe bağlı olarak giriş noktalarından ortaya çıkan basit Python komut dosyaları yazmaktan daha iyi olduğunu göremiyorum.

Python çalıştırma komut dosyasını kullanarak yapılandırılmış bir günlükçü kullanırken örnek günlük çıktısı:

$ ./run.py 
   DEBUG 21:51:22 main.py:95) Configured logging
    INFO 21:51:22 _internal.py:87)  * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
    INFO 21:51:22 _internal.py:87)  * Restarting with inotify reloader
   DEBUG 21:51:22 main.py:95) Configured logging
 WARNING 21:51:22 _internal.py:87)  * Debugger is active!
    INFO 21:51:22 _internal.py:87)  * Debugger pin code: 263-225-431
   DEBUG 21:51:25 inotify_buffer.py:61) in-event <InotifyEvent: src_path=b'my_app/main.py', wd=272, mask=IN_MODIFY, cookie=0, name=b'main.py'>
   DEBUG 21:51:25 inotify_buffer.py:61) in-event <InotifyEvent: src_path=b'my_app/main.py', wd=272, mask=IN_MODIFY, cookie=0, name=b'main.py'>
    INFO 21:51:25 _internal.py:87)  * Detected change in 'my_app/main.py', reloading
    INFO 21:51:26 _internal.py:87)  * Restarting with inotify reloader
   DEBUG 21:51:26 main.py:95) Configured logging
 WARNING 21:51:26 _internal.py:87)  * Debugger is active!
    INFO 21:51:26 _internal.py:87)  * Debugger pin code: 263-225-431

CLI: kullanarak yapılandırılmış bir kaydedici kullanırken örnek günlük çıktısı, kök kaydedicinin işlemde yeterince erken ayarlanamadığına dikkat edin.

$ ./run.sh 
 * Serving Flask app "appsemble.api.main:app"
 * Forcing debug mode on
 * Running on http://127.0.0.1:5000/ (Press CTRL+C to quit)
 * Restarting with inotify reloader
   DEBUG 21:51:33 main.py:95) Configured logging
 * Debugger is active!
 * Debugger pin code: 187-758-498
   DEBUG 21:51:34 main.py:95) Configured logging
   DEBUG 21:51:37 inotify_buffer.py:61) in-event <InotifyEvent: src_path=b'my_app/main.py', wd=272, mask=IN_MODIFY, cookie=0, name=b'main.py'>
   DEBUG 21:51:37 inotify_buffer.py:61) in-event <InotifyEvent: src_path=b'my_app/main.py', wd=272, mask=IN_MODIFY, cookie=0, name=b'main.py'>
 * Detected change in 'my_app/main.py', reloading
    INFO 21:51:37 _internal.py:87)  * Detected change in 'my_app/main.py', reloading
 * Restarting with inotify reloader
    INFO 21:51:38 _internal.py:87)  * Restarting with inotify reloader
 * Debugger is active!
 * Debugger pin code: 187-758-498
   DEBUG 21:51:38 main.py:95) Configured logging

Asıl sorum basitçe:

Flask CLI neden önerilmektedir Flask.run?

Yanıtlar:


11

Geliştirme sunucusu belgelerinde, run () çağırma ve otomatik olarak kodu yeniden yükleme ile ilgili sorunlar olduğunu belirtirler:

Bu yaygın durum için iyi çalışır, ancak geliştirme için iyi çalışmaz, bu nedenle Flask 0.11'den itibaren flask yöntemi önerilir. Bunun nedeni, yeniden yükleme mekanizmasının nasıl çalıştığı nedeniyle bazı tuhaf yan etkilerin olmasıdır (belirli kodu iki kez yürütmek, bazen mesajsız çökmek veya bir sözdizimi veya içe aktarma hatası oluştuğunda ölmek gibi).

CLI'nin bu sorundan muzdarip olmadığını iddia ediyorlar.

Bu konuya değinen ilk taahhüt şudur: https://github.com/pallets/flask/commit/3bdb90f06b9d3167320180d4a5055dcd949bf72f

Ve orada Armin Ronacher şunu yazdı:

Kötü bir şekilde desteklendiğinden, otomatik yeniden yükleme ile geliştirme için bu işlevi kullanmanız önerilmez. Bunun yerine flaskkomut satırı komut dosyasının runserverdesteğini kullanmalısınız.

Aaron Hall tarafından belirtildiği gibi, değiştirilen modüllerde tanımlanan sınıf örnekleri olan tüm nesnelerin yeniden başlatılmaması ve bir modül yeniden yüklendiğinde run () kullanımı sorunlu olabilir. ithal ettiği modüller de yeniden yüklenmiyor.

Bununla ilgili ayrıntılar Python 3 için şu adreste bulunabilir: https://docs.python.org/3/library/importlib.html?highlight=importlib#module-importlib

Belirtir:

Python'daki diğer tüm nesnelerde olduğu gibi, eski nesneler yalnızca referans sayıları sıfıra düştükten sonra geri kazanılır.

Eski nesnelere (modüle harici adlar gibi) yapılan diğer başvurular, yeni nesnelere başvurmak için geri yüklenmez ve istenirse oluştukları her ad alanında güncellenmelidir.

Bir modül yeniden yüklendiğinde, sözlüğü (modülün global değişkenlerini içeren) korunur. Adların yeniden tanımlanması eski tanımları geçersiz kılar, bu nedenle bu genellikle bir sorun değildir. Bir modülün yeni sürümü eski sürüm tarafından tanımlanan bir ad tanımlamazsa, eski tanım kalır.

Böylece, yeni bir süreç oluşturarak ve eskisini öldürerek, tüm eski referansları doğal olarak ortadan kaldırmış olursunuz.

Ayrıca, Flask'ın CLI 'tık' modülünü kullanarak özel komut eklemeyi çok kolaylaştırır, ancak en önemlisi, yeniden yükleme hatasını düzeltmenin yanı sıra CLI, uygulamaları çalıştırmak ve özel komutlar eklemek için standart bir yol sunar. Bu çok iyi bir şey gibi görünüyor, çünkü Flask'a aşinalık, aynı şeyi yapmanın birden fazla yoluna sahip olmak yerine farklı ekipler ve uygulamalar arasında daha aktarılabilir hale getiriyor.

Flask'ı Python Zen'e göre daha fazla yapmanın gerçek bir yolu gibi görünüyor:

Bunu yapmanın tek ve tercihen tek bir yolu olmalı.


2
İşte Armin'in "kötü desteklenmiş" ile ne anlama geldiğini düşünüyorum: Python'da, bir modülü yeniden yüklemek, modülün içe aktardığı modülleri yeniden yüklemez veya diğer modüllerdeki adları yeni nesnelerden yeni nesnelere işaret etmekten yeniden birleştirmez - bu yüzden yeni bir modülü aynı sürece dönüştürmek sorunludur. Kod değişikliği yapmak istediğinizde yeni bir işlem başlatmaktan çok daha iyisiniz.
Aaron Hall

Şimdi bahsettiğinize göre, tarif ettiğiniz davranışı hatırlıyorum, açıklama için teşekkürler! Cevabı buna göre düzenleyeceğim.
Martin Jungblut Schreiner

tamam, artı 1 bana alıntı yaptığım için. :)
Aaron Hall

Aaron Hall'un eklenmesi bunu benim için netleştirdi. Teşekkürler. :)
Remco Haszing

7
Ortam değişkenini neden kullanmalıyız FLASK_APP? Bunun nasıl çalıştığının özü mü? Neden flask runyeni başlayanları daha kolay hale getirecek bir argüman ile aynı şeyi kabul etmediğini merak ediyorum. Teşekkür ederim.
John Wheeler
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.