পাইথনের অনুরোধগুলির সাথে অ্যাসিঙ্ক্রোনাস অনুরোধ


142

পাইথনের অনুরোধ লাইব্রেরির ডকুমেন্টেশনের মধ্যে দেওয়া নমুনার চেষ্টা করেছি ।

এর সাথে async.map(rs), আমি প্রতিক্রিয়া কোডগুলি পাই, তবে আমি অনুরোধ করা প্রতিটি পৃষ্ঠার সামগ্রী পেতে চাই। উদাহরণস্বরূপ, এটি কাজ করে না:

out = async.map(rs)
print out[0].content

আপনি যে প্রতিক্রিয়াগুলি পেয়ে যাচ্ছেন তা শরীরে খালি রয়েছে?
মারিউজ জামরো

আমার জন্য কাজ কর. আপনি যে পুরো ত্রুটি পাচ্ছেন তা পোস্ট করুন।
চিউই

কোন ত্রুটি নেই। এটি কেবল প্রদত্ত পরীক্ষার ইউআরএল দ্বারা চিরকাল চলে runs
trbck

এটি https- র মাধ্যমে ইউআরএল ব্যবহার করার সময় স্পষ্টত উপস্থিত হয়। HTTP ঠিক ঠিক কাজ করছে
trbck

দেখে মনে হচ্ছে requests-threadsএখন আছে।
অরেঞ্জডগ

উত্তর:


154

বিঃদ্রঃ

নীচের উত্তর v0.13.0 + অনুরোধের জন্য প্রযোজ্য নয় । এই প্রশ্নটি লেখার পরে অ্যাসিঙ্ক্রোনাস কার্যকারিতা গ্রেচয়েস্টে স্থানান্তরিত হয়েছিল। তবে, আপনি কেবল নীচে requestsদিয়ে প্রতিস্থাপন করতে পারেন grequestsএবং এটি কাজ করা উচিত।

অনুরোধ <v0.13.0 ব্যবহার করার বিষয়ে যা মূল প্রশ্নটি প্রতিফলিত করতে আমি এই উত্তরটি রেখেছি।


async.map অবিচ্ছিন্নভাবে একাধিক কাজ করতে আপনাকে:

  1. প্রতিটি বস্তুর সাথে আপনি যা করতে চান তার জন্য একটি ফাংশন সংজ্ঞায়িত করুন (আপনার কাজ)
  2. আপনার অনুরোধে ইভেন্ট হুক হিসাবে ফাংশনটি জুড়ুন
  3. async.mapসমস্ত অনুরোধ / ক্রিয়াকলাপের একটি তালিকাতে কল করুন

উদাহরণ:

from requests import async
# If using requests > v0.13.0, use
# from grequests import async

urls = [
    'http://python-requests.org',
    'http://httpbin.org',
    'http://python-guide.org',
    'http://kennethreitz.com'
]

# A simple task to do to each response object
def do_something(response):
    print response.url

# A list to hold our things to do via async
async_list = []

for u in urls:
    # The "hooks = {..." part is where you define what you want to do
    # 
    # Note the lack of parentheses following do_something, this is
    # because the response will be used as the first argument automatically
    action_item = async.get(u, hooks = {'response' : do_something})

    # Add the task to our list of things to do via async
    async_list.append(action_item)

# Do our list of things to do via async
async.map(async_list)

2
আপনার মন্তব্যটি সম্পর্কে ভাল ধারণা রেখেছেন: সর্বশেষতম অনুরোধ এবং গ্রুয়েস্টের মধ্যে সামঞ্জস্যতার কারণে (1.1.0 অনুরোধে ম্যাক্স_রেট্রি বিকল্পের অভাব) অ্যাসিঙ্ক পুনরুদ্ধারের জন্য আমাকে অনুরোধগুলি ডাউনগ্রেড করতে হয়েছিল এবং আমি পেয়েছি যে অ্যাসিঙ্ক্রোনাস কার্যকারিতা 0.13+ সংস্করণে স্থানান্তরিত হয়েছিল ( পিপিআইপিথন.আর.পি.পি.আই. / রিকোয়েস্টস )
বহিরাগত

1
বোবা প্রশ্ন: খালি অনুরোধের বিপরীতে গ্রুয়েস্ট ব্যবহারের গতি বৃদ্ধি কী? অনুরোধ সম্পর্কিত কি সীমা আছে? যেমন async.map এ 3500 টি অনুরোধ করা ঠিক আছে?
ড্রপ

10
from grequests import asyncকাজ না .. এবং আমার জন্য কাজ dosomething এই সংজ্ঞা কি def do_something(response, **kwargs):, আমি তা থেকে এটি stackoverflow.com/questions/15594015/...
অ্যালান নিকুচি

3
যদি async.map কলটি এখনও অবরুদ্ধ করে থাকে, তবে এই অ্যাসিনক্রোনাসটি কীভাবে হয়? অনুরোধগুলি নিজেকে অবিচ্ছিন্নভাবে প্রেরণ করা ছাড়াও, পুনরুদ্ধারটি এখনও সমকালীন?
ব্রায়ান্ফ ২:21

3
আমার জন্য কাজ from requests import asyncকরে প্রতিস্থাপন import grequests as async
মার্টিন থোমা

79

asyncএখন একটি স্বাধীন মডিউল হল: grequests

এখানে দেখুন: https://github.com/kennethreitz/grequests

এবং সেখানে: পাইথনের উপরে একাধিক এইচটিটিপি অনুরোধ প্রেরণের জন্য আদর্শ পদ্ধতি?

স্থাপন:

$ pip install grequests

ব্যবহার:

একটি স্ট্যাক তৈরি:

import grequests

urls = [
    'http://www.heroku.com',
    'http://tablib.org',
    'http://httpbin.org',
    'http://python-requests.org',
    'http://kennethreitz.com'
]

rs = (grequests.get(u) for u in urls)

স্ট্যাকটি প্রেরণ করুন

grequests.map(rs)

ফলাফল মত দেখাচ্ছে

[<Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>, <Response [200]>]

গ্রুয়েস্টগুলি সমবর্তী অনুরোধগুলির জন্য সীমাবদ্ধতা নির্ধারণ করে বলে মনে হয় না, যখন একই সার্ভারে একাধিক অনুরোধ প্রেরণ করা হয়।


11
একযোগে অনুরোধগুলির সীমাবদ্ধতার সাথে - আপনি মানচিত্র () / ইম্যাপ () চালানোর সময় একটি পুলের আকার নির্দিষ্ট করতে পারেন। অর্থ্যাৎ গ্রিকয়েস্ট.ম্যাপ (আরএস, আকার = 20) এর 20 টি সমবর্তী গ্রাব থাকতে হবে।
সিনথেসাইজারপেটেল

1
এখন পর্যন্ত এটি পাইথন 3-সক্ষম নয় (জাইভেন্ট py3.4 এ v2.6 তৈরি করতে ব্যর্থ হয়েছে)।
সার্প

1
আমি অ্যাসিঙ্ক অংশটি বেশ বুঝতে পারি না। যদি আমি results = grequests.map(rs)এই লাইনটি ব্লক হওয়ার পরে কোডটি দিতে পারি, তবে আমি অ্যাসিঙ্ক প্রভাবটি দেখতে পাচ্ছি?
অ্যালান রুইন

47

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

import requests
import concurrent.futures

def get_urls():
    return ["url1","url2"]

def load_url(url, timeout):
    return requests.get(url, timeout = timeout)

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

    future_to_url = {executor.submit(load_url, url, 10): url for url in     get_urls()}
    for future in concurrent.futures.as_completed(future_to_url):
        url = future_to_url[future]
        try:
            data = future.result()
        except Exception as exc:
            resp_err = resp_err + 1
        else:
            resp_ok = resp_ok + 1

এখানে কোন ধরণের ব্যতিক্রম সম্ভব?
হ্যারি হ্যারি

অনুরোধগুলি.অযুক্তি.সামগ্রী
হডজা

2
দুঃখিত আমি আপনার প্রশ্ন বুঝতে পারি না। একাধিক থ্রেডে কেবল একক ইউআরএল ব্যবহার করবেন? কেবলমাত্র একটি কেস ডিডোএস আক্রমণ করে))
হডজা

1
আমি বুঝতে পারছি না কেন এই উত্তরটি এতগুলি উত্সাহ পেল। অ্যাসিঙ্ক অনুরোধ সম্পর্কে ওপি প্রশ্নটি ছিল। থ্রেডপুলএ্যাক্সিকিউটর থ্রেড চালায়। হ্যাঁ, আপনি একাধিক থ্রেডে অনুরোধ করতে পারেন, তবে এটি কখনই একটি অ্যাসিঙ্ক প্রোগ্রাম হবে না, তাই আমি কীভাবে এটি মূল প্রশ্নের উত্তর হতে পারি?
নাগিলিজ

1
আসলে, প্রশ্নটি ছিল কীভাবে সমান্তরালে ইউআরএলগুলি লোড করা যায়। এবং হ্যাঁ থ্রেড পুল নির্বাহক সেরা বিকল্প নয়, অ্যাসিঙ্ক আইও ব্যবহার করা ভাল তবে এটি পাইথনে ভাল কাজ করে। এবং আমি বুঝতে পারি না কেন থ্রেডগুলি অ্যাসিঙ্কের জন্য ব্যবহার করা যায়নি? আপনার যদি সিপিইউ বাউন্ড টাস্ক অ্যাসিক্রোনালি চালানোর দরকার হয়?
হোডজা

29

হয়তো অনুরোধ-ফিউচার অন্য পছন্দ।

from requests_futures.sessions import FuturesSession

session = FuturesSession()
# first request is started in background
future_one = session.get('http://httpbin.org/get')
# second requests is started immediately
future_two = session.get('http://httpbin.org/get?foo=bar')
# wait for the first request to complete, if it hasn't already
response_one = future_one.result()
print('response one status: {0}'.format(response_one.status_code))
print(response_one.content)
# wait for the second request to complete, if it hasn't already
response_two = future_two.result()
print('response two status: {0}'.format(response_two.status_code))
print(response_two.content)

এটি অফিস নথিতেও সুপারিশ করা হয় । আপনি যদি জেনভেটকে জড়িত না করতে চান তবে এটি ভাল।


1
অন্যতম সহজ সমাধান। সর্বাধিক কর্মীদের পরামিতি নির্ধারণ করে সমবর্তী অনুরোধের সংখ্যা বাড়ানো যেতে পারে
জোসে চেরিয়ান

1
এই ছোট আকারের উদাহরণটি দেখতে ভাল লাগবে তাই আমরা লুপ শেষ করতে আইটেম প্রতি একটি পরিবর্তনশীল নাম ব্যবহার করছি না।
ব্যবহারকারী 1717828

অনুরোধ অনুযায়ী একটি থ্রেড থাকা সম্পদ নষ্ট! একসাথে উদাহরণস্বরূপ 500 অনুরোধ করা সম্ভব নয়, এটি আপনার সিপু মেরে ফেলবে। এটি কখনই একটি ভাল সমাধান হিসাবে বিবেচনা করা উচিত নয়।
কর্নেলিউ মাফতুলিয়াক

পছন্দ করুন থ্রেড ব্যবহার সম্পর্কে, আপনার অবশ্যই এটির যত্ন নেওয়া দরকার এবং গ্রন্থাগারটি থ্রেডিং পুল বা প্রসেসিং পুল সক্ষম করার জন্য একটি বিকল্প সরবরাহ করে। ThreadPoolExecutor(max_workers=10)
ড্রিম্পুফ

@ ড্র্যাম্পুফ প্রসেসিং পুল আমার বিশ্বাস আরও খারাপ কি?
কর্নেলিউ মাফতুলিয়াক

11

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

কিছু সমাধান HTTP অনুরোধগুলিতে খাঁটিভাবে কাজ করে, তবে সমাধান অন্য কোনও অনুরোধের জন্য সংক্ষিপ্ত হয়ে পড়ে, যা হাস্যকর। একটি অত্যন্ত কাস্টমাইজড সমাধান এখানে প্রয়োজন হয় না।

কেবলমাত্র পাইথন অন্তর্নির্মিত লাইব্রেরি ব্যবহার করা asyncioযেকোন প্রকারের অ্যাসিনক্রোনাস অনুরোধ সম্পাদন করার পাশাপাশি জটিল এবং ইউজকেস নির্দিষ্ট ত্রুটি পরিচালনার জন্য পর্যাপ্ত তরলতা সরবরাহ করার জন্য যথেষ্ট।

import asyncio

loop = asyncio.get_event_loop()

def do_thing(params):
    async def get_rpc_info_and_do_chores(id):
        # do things
        response = perform_grpc_call(id)
        do_chores(response)

    async def get_httpapi_info_and_do_chores(id):
        # do things
        response = requests.get(URL)
        do_chores(response)

    async_tasks = []
    for element in list(params.list_of_things):
       async_tasks.append(loop.create_task(get_chan_info_and_do_chores(id)))
       async_tasks.append(loop.create_task(get_httpapi_info_and_do_chores(ch_id)))

    loop.run_until_complete(asyncio.gather(*async_tasks))

এটি কীভাবে কাজ করে তা সহজ। আপনি অবিচ্ছিন্নভাবে ঘটতে চান এমন একটি ক্রিয়াকলাপ তৈরি করছেন এবং তারপরে সেই কার্যগুলি সম্পাদন করতে এবং লুপটি শেষ করার পরে বেরিয়ে যেতে বলছেন। কোনও অতিরিক্ত লাইব্রেরি রক্ষণাবেক্ষণের অভাবে, কার্যকারিতার অভাবের বিষয় নয়।


2
আমি যদি সঠিকভাবে বুঝতে পারি তবে জিআরপিসি এবং এইচটিটিপি কল করার সময় এটি ইভেন্ট লুপটি ব্লক করবে? সুতরাং যদি এই কলগুলি শেষ হতে কয়েক সেকেন্ড সময় নেয়, আপনার পুরো ইভেন্টের লুপটি কয়েক সেকেন্ডের জন্য অবরুদ্ধ হবে? এটি এড়াতে আপনার জিআরপিসি বা এইচটিটিপি লাইব্রেরি ব্যবহার করা উচিত async। তারপরে আপনি উদাহরণস্বরূপ করতে পারেন await response = requests.get(URL)। কোন?
কোডার এনআর 23

দুর্ভাগ্যক্রমে, এটি চেষ্টা করার সময়, আমি দেখতে পেলাম যে একটি requestsইউআরএল-এর তালিকাকে সিঙ্ক্রোনালিভাবে কল করার চেয়ে প্রায় একটি মোড়ক তৈরি করা খুব দ্রুত (এবং কিছু ক্ষেত্রে ধীর) is উদাহরণস্বরূপ, উপরের কৌশলটি ব্যবহার করে 10 বার প্রতিক্রিয়া জানাতে একটি শেষ পয়েন্টটির অনুরোধ করা প্রায় 30 সেকেন্ড সময় নেয়। আপনি যদি সত্যিকারের asyncপারফরম্যান্স চান তবে আপনার মতো কিছু ব্যবহার করা দরকার aiohttp
ড্রাগনজোবিজ

8

আমি জানি এটি কিছুক্ষণের জন্য বন্ধ হয়ে গেছে, তবে আমি ভেবেছিলাম অনুরোধের লাইব্রেরিতে নির্মিত আরও একটি অ্যাসিঙ্ক সলিউশন প্রচার করতে এটি দরকারী।

list_of_requests = ['http://moop.com', 'http://doop.com', ...]

from simple_requests import Requests
for response in Requests().swarm(list_of_requests):
    print response.content

দস্তাবেজগুলি এখানে রয়েছে: http://pythonhosted.org/simple-requests/


@ ওয়াইএসওয়াই কোনও সমস্যা পোস্ট করতে নির্দ্বিধায়: github.com/ctheiss/simple-requests/issues ; আমি আক্ষরিকভাবে এই লাইব্রেরিটি দিনে কয়েকবার ব্যবহার করি।
বানর বোসন

বোস্টন, আপনি 404/500 ত্রুটিগুলি কীভাবে পরিচালনা করবেন? https ইউআরএল সম্পর্কে কি? হাজার হাজার url সমর্থন করে এমন স্নিপিংয়ের প্রশংসা করবে। আপনি একটি উদাহরণ পেস্ট করতে পারেন? ধন্যবাদ
YSY

@YSY ডিফল্ট 404/500 ত্রুটি একটি ব্যতিক্রম বাড়াতে। এই আচরণটি ওভাররাইড করা যেতে পারে ( পাইথোনহস্টেড.আর । / সিম্পল-রিকোয়েস্টস / see দেখুন )। জেন্টের উপর নির্ভরতার কারণে এইচটিটিপিএস ইউআরএলগুলি জটিল । আপনি যে টিকিট চালাতে পারেন তাতে একটি শিহর রয়েছে, তবে এটি এসএনআই সার্ভারগুলির জন্য সতর্কতা ফেলে দেবে (তবে এটি কার্যকর হবে )। স্নিপিংয়ের ক্ষেত্রে, আমি ভয় করি যে আমার সমস্ত ব্যবহার আমার সংস্থায় এবং বন্ধ রয়েছে। তবে আমি আপনাকে আশ্বাস দিচ্ছি যে আমরা দশটি কাজের জন্য হাজার হাজার অনুরোধ সম্পাদন করব।
বানর বসন

মিথস্ক্রিয়া ইন্টারঅ্যাকশন সম্মানের সাথে দেখায়। পাইথন 3 + ব্যবহারযোগ্য? দুঃখিত কোন উল্লেখ দেখতে পেল না।
ইসহাক ফিলিপ

@Jethro একেবারে ঠিক আছে, গ্রন্থাগার মোট পুনরায় লেখার যেহেতু অন্তর্নিহিত প্রযুক্তি ডান এখন পাইথন 3 পুরোপুরি ভিন্ন হয় হবে, পাঠাগার "সম্পূর্ণ" হয় কিন্তু শুধুমাত্র পাইথন 2. জন্য কাজ করে
বানর বোসন

4
threads=list()

for requestURI in requests:
    t = Thread(target=self.openURL, args=(requestURI,))
    t.start()
    threads.append(t)

for thread in threads:
    thread.join()

...

def openURL(self, requestURI):
    o = urllib2.urlopen(requestURI, timeout = 600)
    o...

4
এটি থ্রেডগুলিতে "সাধারণ" অনুরোধ। খারাপ উদাহরণ না কেনা অফ-বিষয় is
নিক

4

আপনি যদি অ্যাসিনসিও ব্যবহার করতে চান তবে তারপরে requests-asyncasync / কার্যকারিতাটির জন্য অপেক্ষা করুন সরবরাহ করে requests- https://github.com/encode/requests-async


2
নিশ্চিত, দুর্দান্ত কাজ করে। প্রকল্পের পৃষ্ঠায় এটি বলেছে যে নীচের প্রকল্পটি github.com/encode/httpx
nurettin

2

আমি কিছু সময়ের জন্য গিথুবের জিস্ট এপিআইয়ের বিরুদ্ধে অ্যাসিঙ্ক কলগুলির জন্য পাইথন অনুরোধগুলি ব্যবহার করছি।

উদাহরণস্বরূপ, কোডটি এখানে দেখুন:

https://github.com/davidthewatson/flasgist/blob/master/views.py#L60-72

পাইথনের এই স্টাইলটি সবচেয়ে পরিষ্কার উদাহরণ নাও হতে পারে তবে আমি আপনাকে আশ্বাস দিতে পারি যে কোডটি কাজ করে। এটি আপনার কাছে বিভ্রান্তিযুক্ত কিনা তা আমাকে জানান এবং আমি এটি দলিল করব will


2

আপনি এটি httpxজন্য ব্যবহার করতে পারেন ।

import httpx

async def get_async(url):
    async with httpx.AsyncClient() as client:
        return await client.get(url)

urls = ["http://google.com", "http://wikipedia.org"]

# Note that you need an async context to use `await`.
await asyncio.gather(*map(get_async, urls))

আপনি যদি একটি কার্যকরী বাক্য গঠন চান, গামলা লিবিব এটিকে আবৃত করে get_async

তাহলে আপনি করতে পারেন


await gamla.map(gamla.get_async(10), ["http://google.com", "http://wikipedia.org"])

10সেকেন্ডের মধ্যে সময় ফুরিয়ে গেছে।

(অস্বীকৃতি: আমি এর লেখক)


এবং respxঠাট্টা / পরীক্ষার জন্য :)
rt

0

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

http://pythonquirks.blogspot.com/2011/04/twisted-asynchronous-http-request.html


পাকানো পুরানো ed পরিবর্তে HTTPX ব্যবহার করুন।
আমিরহসিন
আমাদের সাইট ব্যবহার করে, আপনি স্বীকার করেছেন যে আপনি আমাদের কুকি নীতি এবং গোপনীয়তা নীতিটি পড়েছেন এবং বুঝতে পেরেছেন ।
Licensed under cc by-sa 3.0 with attribution required.