কীভাবে আমি অ্যাসিনসিওতে অনুরোধগুলি ব্যবহার করতে পারি?


126

আমি সমান্তরাল HTTP অনুরোধ কাজগুলিতে করতে চাই asyncio, তবে আমি দেখতে পাচ্ছি যে python-requestsইভেন্টটির লুপটি ব্লক করবে asyncio। আমি আইওএইচটিপি খুঁজে পেয়েছি তবে এটি কোনও http প্রক্সি ব্যবহার করে http অনুরোধের পরিষেবা সরবরাহ করতে পারেনি।

সুতরাং আমি জানতে চাই যে সহায়তার সাথে অ্যাসিঙ্ক্রোনাস http অনুরোধ করার কোনও উপায় আছে কিনা asyncio


1
আপনি যদি কেবল অনুরোধগুলি প্রেরণ করছেন তবে আপনি subprocessনিজের কোডটি সমান্তরাল করতে ব্যবহার করতে পারেন ।
ওয়েজেলফক্স

এই পদ্ধতিটি মার্জিত নয় বলে মনে হচ্ছে ……
ফ্লায়ার

অনুরোধের একটি অ্যাসিনসিও পোর্ট এখন আছে। github.com/rdbhost/yeldfromRequests
Rdbhost

উত্তর:


181

অ্যাসিনসিও সহ অনুরোধগুলি (বা অন্য কোনও ব্লক করা লাইব্রেরি) ব্যবহার করতে, আপনি অন্য থ্রেডে কোনও ক্রিয়াকলাপ চালাতে বেসএভেন্টলুপ.আরুন_ইন_এক্সিকিউটর ব্যবহার করতে পারেন এবং ফলাফলটি পেতে এটি থেকে ফলন করতে পারেন। উদাহরণ স্বরূপ:

import asyncio
import requests

@asyncio.coroutine
def main():
    loop = asyncio.get_event_loop()
    future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com')
    future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk')
    response1 = yield from future1
    response2 = yield from future2
    print(response1.text)
    print(response2.text)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

এটি উভয় প্রতিক্রিয়া সমান্তরালে পাবেন।

অজগর 3.5 দিয়ে আপনি নতুন await/ asyncসিনট্যাক্সটি ব্যবহার করতে পারেন :

import asyncio
import requests

async def main():
    loop = asyncio.get_event_loop()
    future1 = loop.run_in_executor(None, requests.get, 'http://www.google.com')
    future2 = loop.run_in_executor(None, requests.get, 'http://www.google.co.uk')
    response1 = await future1
    response2 = await future2
    print(response1.text)
    print(response2.text)

loop = asyncio.get_event_loop()
loop.run_until_complete(main())

আরও জানতে PEP0492 দেখুন।


5
আপনি ঠিক কীভাবে এটি কাজ করে তা ব্যাখ্যা করতে পারেন? আমি বুঝতে পারি না এটি কীভাবে অবরুদ্ধ হয় না।
স্কট কোয়েটস

32
@ ক্রিশ্চিয়ান তবে এটি যদি একই সাথে অন্য থ্রেডে চলতে থাকে তবে এটি কি অ্যাসিনসিওর পয়েন্টকে পরাস্ত করে না?
স্কট কোয়েটস

21
@scoarescoare সেখানেই 'যদি আপনি এটি সঠিকভাবে করেন' অংশটি আসে - আপনি নির্বাহকের যে পদ্ধতিতে চালিত হন তা স্বাবলম্বিত হওয়া উচিত ((বেশিরভাগই) অনুরোধের মতো (উপরের উদাহরণে)। এইভাবে আপনাকে ভাগ করা মেমরি, লকিং ইত্যাদির সাথে ডিল করতে হবে না এবং আপনার প্রোগ্রামের জটিল অংশগুলি এখনও অ্যাসিনসিওকে ধন্যবাদ একক থ্রেডযুক্ত।
খ্রিস্টান

5
@scoarescoare মূল ব্যবহারের ক্ষেত্রটি IO গ্রন্থাগারগুলির সাথে সংহত করার জন্য যা অ্যাসিনসিওর সমর্থন করে না। উদাহরণস্বরূপ, আমি সত্যই প্রাচীন এসওএপি ইন্টারফেসের সাথে কিছু কাজ করছি এবং আমি সুডস-জুরকো লাইব্রেরিটিকে "কমপক্ষে খারাপ" সমাধান হিসাবে ব্যবহার করছি। আমি এটিকে একটি অ্যাসিনসিও সার্ভারের সাথে সংহত করার চেষ্টা করছি, তাই আমি ব্লকিং সুড কলগুলি এমনভাবে দেখায় যা অ্যাসিঙ্ক্রোনাস দেখায় in
লুক্রেটিয়েল

10
লিগ্যাসি স্টাফগুলির পক্ষে এটি কার্যকর এবং এটি এত সহজ যে সত্যই শীতল, তবে এটির ওএস থ্রেডপুল ব্যবহার করা উচিত এবং এটিও এইচআইএইচটিপি এর মতো সত্যিকারের অ্যাসিনসিও ওরিয়েন্টেড লিব হিসাবে স্কেল করা যায় না
জেসাল্টার

78

এআইওএইচটিপি ইতিমধ্যে HTTP প্রক্সি দিয়ে ব্যবহার করা যেতে পারে:

import asyncio
import aiohttp


@asyncio.coroutine
def do_request():
    proxy_url = 'http://localhost:8118'  # your proxy address
    response = yield from aiohttp.request(
        'GET', 'http://google.com',
        proxy=proxy_url,
    )
    return response

loop = asyncio.get_event_loop()
loop.run_until_complete(do_request())

সংযোজকটি এখানে কী করে?
মার্কাস মেসকেনেন

এটি প্রক্সি সার্ভারের মাধ্যমে একটি সংযোগ সরবরাহ করে
মাইন্ডমাস্টার

16
পৃথক থ্রেডে অনুরোধগুলি ব্যবহার করার পরে এটি আরও অনেক ভাল সমাধান। যেহেতু এটি সত্যই অ্যাসিঙ্ক তাই এটির ওভারহেড কম এবং মেমের ব্যবহার কম।
থম

14
পাইথন> = 3.5 এর জন্য @ asyncio.coroutine কে "async" এর সাথে প্রতিস্থাপন করুন এবং "অপেক্ষা" সহ "থেকে" ফলন দিন
জেমস

40

উপরের উত্তরগুলি এখনও পুরানো পাইথন 3.4 স্টাইলের কর্টিনগুলি ব্যবহার করছে। পাইথন ৩.৫+ পেয়ে গেলে আপনি কী লিখবেন তা এখানে।

aiohttp এখন HTTP প্রক্সি সমর্থন করে

import aiohttp
import asyncio

async def fetch(session, url):
    async with session.get(url) as response:
        return await response.text()

async def main():
    urls = [
            'http://python.org',
            'https://google.com',
            'http://yifei.me'
        ]
    tasks = []
    async with aiohttp.ClientSession() as session:
        for url in urls:
            tasks.append(fetch(session, url))
        htmls = await asyncio.gather(*tasks)
        for html in htmls:
            print(html[:100])

if __name__ == '__main__':
    loop = asyncio.get_event_loop()
    loop.run_until_complete(main())

1
আপনি আরও ইউআরএল দিয়ে বিস্তারিত বলতে পারেন? যখন প্রশ্নটি সমান্তরাল HTTP অনুরোধটি সম্পর্কিত তখন কেবল একটিই ইউআরএল থাকা অর্থহীন নয়।
বেনামে

লেজেন্ড। ধন্যবাদ! দুর্দান্ত কাজ করে
আদম

@ স্পাইডার এই কোডটি কীভাবে সমান্তরালভাবে 100 টি অনুরোধ ব্যবহার করে 10 কে ইউআরএল সরবরাহ করতে সংশোধন করা যেতে পারে? ধারণা অর্ডার পরবর্তী 100 শুরু করার মধ্যে বিতরণ করা হবে একযোগে সব 100 স্লট ব্যবহার করতে, 100 জন্য অপেক্ষা করতে হয় না
Antoan Milkov

@ আন্টানমিলকভ এটি পৃথক প্রশ্ন যা মন্তব্যের ক্ষেত্রে উত্তর দেওয়া যায় না।
অস্পাইডার

: @ospider আপনি ঠিক, এখানে প্রশ্ন হল stackoverflow.com/questions/56523043/...
Antoan Milkov

11

অনুরোধগুলি বর্তমানে সমর্থন করে না asyncioএবং এই জাতীয় সহায়তা দেওয়ার কোনও পরিকল্পনা নেই। সম্ভবত আপনি একটি কাস্টম "ট্রান্সপোর্ট ট্রান্সপোর্ট অ্যাডাপ্টার" প্রয়োগ করতে পারেন ( এখানে আলোচনা করা হয়েছে ) যা কীভাবে ব্যবহার করতে হয় তা জানে asyncio

আমি যদি নিজেকে কিছু সময়ের সাথে খুঁজে পাই তবে এটি এমন কিছু যা আসলে আমি সন্ধান করতে পারি তবে আমি কোনও প্রতিশ্রুতি দিতে পারি না।


লিঙ্কটি 404 এর দিকে নিয়ে যায়
কোডবিকার

8

পাইথন এবং অ্যাসিনসিওর সাথে পিমিন কনস্ট্যান্টিন কেফালোউকোস ইজি সমান্তরাল এইচটিটিপি অনুরোধের একটি নিবন্ধে অ্যাসিঙ্ক / অপেক্ষার লুপগুলি এবং থ্রেডিংয়ের একটি ভাল কেস রয়েছে :

মোট সমাপ্তির সময়টি হ্রাস করতে, আমাদের যে অনুরোধগুলি করতে হবে তার সংখ্যার সাথে মিলিয়ে আমরা থ্রেড পুলের আকার বাড়িয়ে তুলতে পারি। ভাগ্যক্রমে, এটি পরবর্তী কাজ হিসাবে করা সহজ হিসাবে করা সহজ। নীচে কোড তালিকাটি বিশ কর্মী থ্রেডের একটি থ্রেড পুল সহ বিশ অ্যাসিনক্রোনাস এইচটিটিপি অনুরোধগুলি কীভাবে তৈরি করবেন তার একটি উদাহরণ:

# Example 3: asynchronous requests with larger thread pool
import asyncio
import concurrent.futures
import requests

async def main():

    with concurrent.futures.ThreadPoolExecutor(max_workers=20) as executor:

        loop = asyncio.get_event_loop()
        futures = [
            loop.run_in_executor(
                executor, 
                requests.get, 
                'http://example.org/'
            )
            for i in range(20)
        ]
        for response in await asyncio.gather(*futures):
            pass


loop = asyncio.get_event_loop()
loop.run_until_complete(main())

2
এটির সাথে সমস্যাটি হ'ল যদি আমার ২০ টি এক্সিকিউটারের অংশ নিয়ে 10000 অনুরোধ চালানোর দরকার হয় তবে পরবর্তী 20 টি দিয়ে শুরু করার জন্য আমাকে সমস্ত 20 এক্সিকিউটারের অপেক্ষা করতে হবে, তাই না? আমি এর জন্য করতে পারি না for i in range(10000)কারণ একটি অনুরোধ ব্যর্থ হতে পারে বা সময়সীমা শেষ হতে পারে, তাই না?
সানান্দ্রিয়া

1
আপনি যখন থ্রেডপুলএকসিকিউটার ব্যবহার করে একই কাজ করতে পারেন তখন কেন আপনার অ্যাসিনসিও দরকার হয় আপনি দয়া করে ব্যাখ্যা করতে পারেন?
আসফ পিনহাসি

@ ইলিয়া রসিন কিসের উপর ভিত্তি করে আমরা ম্যাক্স ওয়ার্কার্সের সংখ্যা নির্ধারণ করি? এটির কি সিপিইউ এবং থ্রেডের সংখ্যার সাথে সম্পর্ক আছে?
alt-f4
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.