Streamowanie responsa do requesta

0

Taki oto case mnie zastał: mamy duży plik pod adresem xd.pl/plik.jpg no i teraz ten plik trzeba pobrać i wysłać pod endpoint niexd.pl/put
ten pliczek jeest na tyle duży, że do pamięci ani na dysk maszyny go nie pobiorę, stąd też trzeba by zrobić coś na zasadzie: czytam sobie chunk z responsa get z plikiem, ten chunk sobie streamuje w jakiś sposób na ednpoint. Tldr; bycie niejako takim proxy między responsem z urla a endpointem.

Próbowałem z requests. Nie obsługują putów streamowanych. Requests toolbelt - mają obsługę streamowanych putów i nawet coś takiego jak FileFromURLWrapper, ale tu z kolei nie pobiera mi kompletnego pliku i i tak żre pamięć. Jest jeszcze dugong, który wyglądał obiecująco z coroutines, ale nie udało mi się sprawić, by zadziałał.

Czy macie jakieś pomysły, jak to rozwiązać? Nie musi być Python - może być dowolny inny język, ostatecznie nawet coś z unixowych rzeczy, ale to raczej wolałbym zachować jako naprawdę ostateczność.

1

Jak się okazało wystarczyło przestać kombinować i zrobić po prostu:

import requests

def wrapper():
    with requests.get('URL', stream=True) as r:
        for chunk in r.iter_content(chunk_size=4096):
            if chunk:
                yield chunk

resp = requests.put('http://0.0.0.0:81/put', data=wrapper())

Dzięki Gordi za pomysł.

2

Pętla jest niepotrzebna:

...
    with requests.get('URL', stream=True) as r:
        yield from r.iter_content(chunk_size=4096):
...

yield from (PEP 380) jest w języku od wersji 3.3.

Ja wybrałbym jednak inne rozwiązanie:

$ curl <URL1> | curl -T - <URL2>
0

@Mózg: świetnie, dzięki, jeszcze krócej!
anyway
Dlaczego preferowałbyś curla w tym wypadku?
Wydaje mi się, że lepiej zostawić to w Pythonie - raz, że reszta jest w pythonie i walenie po prostu subprocessem wywołania curla byłoby kapke nieeleganckie, to dwa, wtedy trudniej byłoby mi logować rzeczy typu response code, response content itd
Może za curlem przemawia coś o czym nie wiem

0

W sumie to zysk jaki widzę, to możliwość puszczenia curla jako detached process bez blokowania wykonania reszty, ale może jest jeszcze coś?

Btw. subprocess i tak pozwala się dobrać np. do kodów zwracanych przez procesy czy stderr, więc może nie byłoby źle? :)

0

Jasne, do error kodów możesz się dobrać bez problemu, tam samo do stdout czy err, ale nie oferuje mi to takich szczegółów jak pythonowy response I think

No i tutaj nic nie blokujemy - to jest fragment spawnowanego asynchronicznego workera w zupełnie oddzielnym procesie niż cała reszta

0

reszta jest w pythonie

Reszta? Nie napisałeś, że to część większego programu.

Dlaczego preferowałbyś curla w tym wypadku?

Ponieważ curl został stworzony do tego typu zadań. Jest to ponad 20-letni, doświadczony w dziczy projekt. Liczne opcje pozwalają w prosty sposób m.in. wznawiać przerwane połączenia, ograniczyć prędkość pobierania/wysyłania. Nie widzę potrzeby robienia czegoś w Pythonie, jeżeli mogę to zrobić (bezboleśnie) w shellu.

0

Dziękuję za odpowiedzi, w tym konkretnym przypadku użyłem pythona i yield from ostatecznie.

1 użytkowników online, w tym zalogowanych: 0, gości: 1