Rozmawiałem dzisiaj z moim kolegą na temat frameworków internetowych Pythona i naszych wrażeń na ich temat. Powiedziałem mu, że myślę, że Flask, który ma globalne życzenie, źle pachnie i jest anty-wzorem.
W docs powiedzieć o kontekście żądanie:
Natomiast podczas obsługi żądań istnieje kilka innych reguł:
- gdy żądanie jest aktywne, kontekstowe obiekty lokalne (flask.request i inne) wskazują na bieżące żądanie.
- dowolny kod może uzyskać te obiekty w dowolnym momencie.
Myślę, że rozumiem ideę tej decyzji projektowej - uproszczenie aplikacji. To tylko kompromis, jak w przypadku Lokalnych wątków :
Tak, zwykle nie jest tak dobrym pomysłem stosowanie miejscowych wątków. Powodują problemy dla serwerów, które nie są oparte na koncepcji wątków i utrudniają utrzymanie dużych aplikacji. Jednak Flask po prostu nie jest przeznaczony do dużych aplikacji lub serwerów asynchronicznych. Flask chce, aby pisanie tradycyjnej aplikacji internetowej było szybkie i łatwe.
Czy łatanie obiektu globalnego informacjami o bieżącym żądaniu jest anty-wzorcem?
Wierzę, że tak jest, ponieważ zdaniem analizatora kodów statycznych jest to stan globalny, chociaż tak nie jest. A ja jako programista nie zrozumiem, jak to działa bez uważnego przeczytania dokumentacji . Ma to konsekwencje dla testów .
Czy nie jest dobrą praktyką przekazywanie żądania jako argumentu do widoków? Myślę, że jest bardziej czytelny, wyraźny i łatwiejszy do debugowania. I unika stanu globalnego.
źródło
Odpowiedzi:
Wiele frameworków ma tę samą strukturę: żądanie globalne. W pewnym sensie jest to właściwe, ponieważ hej, tak naprawdę jest tylko jedna prośba na raz.
Czy jest więc sens przekazywanie żądania jako parametru? Nie. Żądanie jest żądaniem, a parametry dotyczą przekazywania różnych rzeczy w różnych momentach.
Prawdziwym problemem jest jak zaczniesz rozważać niższe poziomy większego zastosowania. W przypadku globalnego żądania istnieje pokusa, aby pisać kod w całym miejscu, w którym globalnie uzyskuje się dostęp do żądania. To bardzo zła rzecz . Powoduje sprzężenie między różnymi częściami kodu, utrudnia zmianę rzeczy i utrudnia testowanie rzeczy.
Więc moja odpowiedź brzmi: zachowaj globalną prośbę i żyj z nią. Jednak wszędzie tam, gdzie pojedynczy moduł lub funkcja nie potrzebuje całego żądania, jako parametr przekaż tylko potrzebne dane. Przekaż tylko polecenia, adres URL lub ogon polecenia i dowolne potrzebne bity do swoich funkcji. Pomoże to utrzymać modułowość kodu, zmniejszy sprzężenie i poprawi testowalność.
W przypadku małych programów nie ma to większego znaczenia, ale w przypadku większych może to być prawdziwy ratownik.
źródło
(Zamierzam odważnie i odpowiem na to pytanie, chociaż mogę dostać trochę głosów negatywnych).
Kolba jest mikrocząsteczką; korzystasz z prostoty, rezygnując z dodatków. Chociaż jestem na poziomie jelit, zgadzam się z tobą, wiem, że użyłem flask + gunicorn w jednym sklepie, aby dać mi wielowątkowość, której potrzebowałem. Działa naprawdę dobrze. Każde wystąpienie skryptu po prostu obsłużyło jedno żądanie (tj. Jeden wątek), a gunicorn obsłużył „fan out” wśród wielu wątków. Było w tym świetnie.
Więc odczuwany minus, który odczuwasz - że wiele wątków może walczyć o stan globalny - po prostu nie stanowi problemu, ponieważ jest to jeden skrypt na wątek.
(Tutaj mogę wpaść w kłopoty) Wątki i współbieżność są po prostu inne w świecie Pythona, a jeśli przyjdziesz do tego z umysłem Java, trudno to wcisnąć. Moje doświadczenie było takie, że problemy z współbieżnością, które wziąłem za przyznane w Javie lub obsługiwane przezroczyście przez kontener aplikacji, są znacznie bliżej powierzchni w Pythonie.
Dziwne mi było, że jeden wątek poradziłby sobie z jednym wywołaniem mojego skryptu, ale po tym, jak kilkadziesiąt uruchomiłem jednocześnie na pudełku, poczułem się lepiej.
źródło
W Pythonie masz
print
polecenie (funkcja od wersji 3), które wypisuje na standardowe wyjście. Nie określasz jawnie, że chcesz drukować do STDOUT - jest to zrobione dla ciebie niejawnie za kulisami.Niejawnie. W Pythonie. I nikt nie ma z tym problemu. Czemu?
print
jest częścią języka Python, a jednym z wymogów programowania w języku Python jest ... no cóż ... znajomość języka Python. A jeśli znasz Python, wiesz, że jest onprint
ukierunkowany na STDOUT. Żadnych niespodzianek.Python - jako język - może zdefiniować własną konwencję i założyć, że programiści są tego świadomi.
Frameworki również korzystają z tego przywileju - to jedna z kluczowych różnic między frameworkiem a biblioteką. Nie musisz uczyć się biblioteki, aby z niej korzystać - wystarczy znaleźć potrzebną część interfejsu API i założyć, że jest on zgodny z konwencjami języka (lub frameworka). Dlatego nie widzisz rekruterów szukających ludzi z wiedzą w GSON lub Apache Commons. Ale widzisz rekruterów szukających ludzi z doświadczeniem w JQuery lub Ruby on Rails lub ASP.NET MVC - ponieważ są to ramy, które definiują własne konwencje, których musisz się nauczyć i być świadomym.
Flask, jako struktura, może definiować konwencję przechowywania kontekstu w globalnym wątku lokalnym - i nie powinien nikogo dziwić, więc nie jest to anty-wzorzec.
źródło
sys.stdout
. Jeśli to zmienisz, druk trafi gdzie indziej.>>
operatora lub przekazującfile
argument doprint
działania w Python3. Tak,sys.stdout
to tylko wartość domyślną, która może być zmieniona.