Skip to content

Commit f9573d0

Browse files
Merge pull request #298 from dspetrenko/async_download
Async downloading example
2 parents 7dd03ca + 6bcb7b8 commit f9573d0

File tree

2 files changed

+128
-0
lines changed

2 files changed

+128
-0
lines changed

async_downloader/async_downloader.py

+127
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,127 @@
1+
"""
2+
It's example of usage asyncio+aiohttp to downloading.
3+
4+
You should install aiohttp for using:
5+
(You can use virtualenv to testing)
6+
7+
pip install -r /path/to/requirements.txt
8+
9+
"""
10+
11+
import asyncio
12+
import aiohttp
13+
from os.path import basename
14+
import concurrent.futures as cofu
15+
16+
17+
def download(ways):
18+
19+
if not ways:
20+
print('Ways list is empty. Downloading is impossible')
21+
return
22+
23+
print('downloading..')
24+
25+
success_files = set()
26+
failure_files = set()
27+
28+
event_loop = asyncio.get_event_loop()
29+
try:
30+
event_loop.run_until_complete(
31+
async_downloader(ways, event_loop, success_files, failure_files)
32+
)
33+
finally:
34+
event_loop.close()
35+
36+
print('Download complete')
37+
print('-' * 100)
38+
39+
if success_files:
40+
print('success:')
41+
for file in success_files:
42+
print(file)
43+
44+
if failure_files:
45+
print('failure:')
46+
for file in failure_files:
47+
print(file)
48+
49+
50+
async def async_downloader(ways, loop, success_files=set(), failure_files=set()):
51+
52+
async with aiohttp.ClientSession() as session:
53+
coroutines = [
54+
download_file_by_url(
55+
url,
56+
session=session,
57+
) for url in ways]
58+
59+
completed, pending = await asyncio.wait(coroutines, return_when=cofu.FIRST_COMPLETED)
60+
while pending:
61+
62+
for task in completed:
63+
fail, url = task.result()
64+
65+
if fail:
66+
failure_files.add(url)
67+
else:
68+
success_files.add(url)
69+
70+
completed, pending = await asyncio.wait(pending, return_when=cofu.FIRST_COMPLETED)
71+
72+
for task in completed:
73+
fail, url = task.result()
74+
if fail:
75+
failure_files.add(url)
76+
else:
77+
success_files.add(url)
78+
79+
80+
async def download_file_by_url(url, session=None):
81+
82+
fail = True
83+
file_name = basename(url)
84+
85+
assert session
86+
87+
try:
88+
async with session.get(url) as response:
89+
if response.status == 404:
90+
print('\t{} from {} : Failed : {}'.format(file_name, url, '404 - Not found'))
91+
return fail, url
92+
93+
if not response.status == 200:
94+
print('\t{} from {} : Failed : HTTP response {}'.format(file_name, url, response.status))
95+
return fail, url
96+
97+
data = await response.read()
98+
99+
with open(file_name, 'wb') as file:
100+
file.write(data)
101+
102+
except asyncio.TimeoutError as err:
103+
print('\t{} from {}: Failed : {}'.format(file_name, url, 'Timeout error'))
104+
105+
except aiohttp.client_exceptions.ClientConnectionError as err:
106+
print('\t{} from {}: Failed : {}'.format(file_name, url, 'Client connection error'))
107+
108+
else:
109+
print('\t{} from {} : Success'.format(file_name, url))
110+
fail = False
111+
112+
return fail, url
113+
114+
115+
def test():
116+
117+
ways = ['https://www.wikipedia.org',
118+
'https://www.ya.ru',
119+
'https://www.duckduckgo.com',
120+
'https://www.fail-path.unknown',
121+
]
122+
123+
download(ways)
124+
125+
126+
if __name__ == "__main__":
127+
test()

async_downloader/requirements.txt

+1
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
aiohttp==2.1.0

0 commit comments

Comments
 (0)