ทางเลือก CURL ใน Python


114

ฉันมีการโทร cURL ที่ฉันใช้ใน PHP:

curl -i -H 'Accept: application / xml' -u login: key " https://app.streamsend.com/emails "

ฉันต้องการวิธีทำสิ่งเดียวกันใน Python มีทางเลือกอื่นนอกเหนือจาก cURL ใน Python หรือไม่ ฉันรู้จัก urllib แต่ฉันเป็น Python noob และไม่รู้ว่าจะใช้มันอย่างไร


2
คุณสามารถลองpycurl
ghostdog74

2
urllib2 เป็นแพ็คเกจที่ใช้กันอย่างแพร่หลายสำหรับงานประเภทนี้
Saurav

7
ดียิ่งขึ้น: docs.python-requests.org/en/latest/index.html
Saurav

3
ด้านบนเป็นลิงค์สำหรับไลบรารีที่ยอดเยี่ยมในการทำ http ง่ายๆrequestsใน python (พร้อมให้ติดตั้งผ่าน easy_install หรือ pip ใน PyPi) ชื่อ / URL สับสนเล็กน้อย - ตอนแรกฉันเกือบคิดว่านี่เป็นคำขอสิ่งที่อยากได้เพื่อสิ่งที่ดีกว่าurllib2แทนที่จะrequestsเป็นไลบรารี pythonic ที่ใช้งานง่ายมากsudo easy_install requestsหรือsudo pip install requests.
dr jimbob

คำขอ Python เทียบกับประสิทธิภาพของ PyCurlคุณเหมาะสมกับความต้องการของคุณ
Santhosh

คำตอบ:


68
import urllib2

manager = urllib2.HTTPPasswordMgrWithDefaultRealm()
manager.add_password(None, 'https://app.streamsend.com/emails', 'login', 'key')
handler = urllib2.HTTPBasicAuthHandler(manager)

director = urllib2.OpenerDirector()
director.add_handler(handler)

req = urllib2.Request('https://app.streamsend.com/emails', headers = {'Accept' : 'application/xml'})

result = director.open(req)
# result.read() will contain the data
# result.info() will contain the HTTP headers

# To get say the content-length header
length = result.info()['Content-Length']

การโทร cURL ของคุณโดยใช้ urllib2 แทน ยังไม่ทดลองโดยสิ้นเชิง


4
เป็นการดีที่จะเปรียบเทียบสิ่งนี้กับคำตอบด้านล่างและดูว่า Python ก้าวหน้าแค่ไหนในช่วงสี่ปีที่ผ่านมา
Razi Shaban

133

คุณสามารถใช้คำขอ HTTP ที่อธิบายไว้ในคู่มือผู้ใช้คำขอ: HTTP for Humans


2
คำขอล่าสุดและยิ่งใหญ่ที่สุด! มันสูบบุหรี่และเผา urllib2 เงอะงะฉันต้องการให้คำขอกลายเป็นไคลเอนต์ HTTP มาตรฐานสำหรับหลามเวอร์ชัน 3.x ที่เข้ามา
Phyo Arkar Lwin

1
เมื่อฉันเปลี่ยนไปใช้คำขอฉันไม่เคยหันกลับไปใช้ urllib2 โดยตรงอีกต่อไป การถอดรหัส JSON ในตัวนั้นมีประโยชน์เช่นกัน ไม่จำเป็นต้องโหลดเนื้อหาด้วย json ด้วยตนเองหากตั้งค่าประเภทเนื้อหาที่เหมาะสม
Thomas Farvour

คำขอนั้นง่ายมาก ฉันยังสามารถสร้างรูปแบบการตรวจสอบสิทธิ์แบบกำหนดเองได้ในเวลาไม่กี่นาที urllib2 น่ารำคาญมาก
Doug

35

นี่คือตัวอย่างง่ายๆโดยใช้ urllib2 ที่ตรวจสอบสิทธิ์พื้นฐานกับ API ของ GitHub

import urllib2

u='username'
p='userpass'
url='https://api.github.com/users/username'

# simple wrapper function to encode the username & pass
def encodeUserData(user, password):
    return "Basic " + (user + ":" + password).encode("base64").rstrip()

# create the request object and set some headers
req = urllib2.Request(url)
req.add_header('Accept', 'application/json')
req.add_header("Content-type", "application/x-www-form-urlencoded")
req.add_header('Authorization', encodeUserData(u, p))
# make the request and print the results
res = urllib2.urlopen(req)
print res.read()

นอกจากนี้หากคุณรวมสิ่งนี้ไว้ในสคริปต์และเรียกใช้จากเทอร์มินัลคุณสามารถไพพ์สตริงการตอบกลับไปที่ 'mjson.tool' เพื่อเปิดใช้งานการพิมพ์แบบสวย ๆ

>> basicAuth.py | python -mjson.tool

สิ่งสุดท้ายที่ควรทราบ urllib2 รองรับคำขอ GET & POST เท่านั้น
หากคุณต้องการใช้คำกริยา HTTP อื่น ๆ เช่น DELETE, PUT ฯลฯ คุณอาจต้องการดูPYCURL


เหตุใดจึงได้รับการโหวตให้ลดลง อาจเป็นเพราะคุณเขียน PYCURL แทน PycURL: D
Bhargav Rao

20

หากคุณใช้คำสั่งเพื่อเรียก curl แบบนั้นคุณสามารถทำสิ่งเดียวกันใน Python ด้วยsubprocess. ตัวอย่าง:

subprocess.call(['curl', '-i', '-H', '"Accept: application/xml"', '-u', 'login:key', '"https://app.streamsend.com/emails"'])

หรือคุณอาจลองใช้PycURLหากต้องการให้เป็น API ที่มีโครงสร้างมากขึ้นเช่นเดียวกับที่ PHP มี


ไม่การโทร cURL เป็นส่วนหนึ่งของโปรแกรม หากคุณสามารถโพสต์โค้ดที่ทำสิ่งเดียวกันกับที่ทำในการเรียก curl ด้านบนนั่นจะดีมาก
Gaurav Sharma

เพิ่มตัวอย่างของสิ่งที่ฉันหมายถึงโดยใช้กระบวนการย่อยตามคำถามของคุณ แต่ฉันเดาว่าคุณกำลังมองหาบางอย่างเช่น PycURL
unholysampler

ฉันรู้ว่าสิ่งนี้เก่ากว่า แต่ PycURL ค่อนข้างต่ำสำหรับการใช้ cURL ส่วนใหญ่ในความคิดของฉัน แม้แต่การใช้งาน PHP ของ cURL ก็อยู่ในระดับที่ค่อนข้างต่ำ
Thomas Farvour

ฉันได้รับ "ข้อผิดพลาดชื่อกระบวนการย่อยไม่ได้กำหนดชื่อ" หลังจากเรียก "python" จาก cmd ดังนั้นจึงอยู่ใน python env
Timo

@Timo รึเปล่า import subprocessเปล่า? สภาพแวดล้อมการจำลอง python ก็เหมือนกับไฟล์ python คุณต้องนำเข้าโมดูลอื่น ๆ
unholysampler

13
import requests

url = 'https://example.tld/'
auth = ('username', 'password')

r = requests.get(url, auth=auth)
print r.content

นี่เป็นวิธีที่ง่ายที่สุดที่ฉันเคยทำได้


นี่คือคำตอบที่ง่ายที่สุด! urllib2ซับซ้อนเกินไป
not2qubit

7

ตัวอย่างเช่นวิธีใช้ urllib สำหรับสิ่งนั้นด้วยไวยากรณ์น้ำตาล ฉันรู้เกี่ยวกับคำขอและไลบรารีอื่น ๆ แต่ urllib เป็น lib มาตรฐานสำหรับ python และไม่จำเป็นต้องติดตั้งอะไรแยกต่างหาก

เข้ากันได้กับ Python 2/3

import sys
if sys.version_info.major == 3:
  from urllib.request import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, Request, build_opener
  from urllib.parse import urlencode
else:
  from urllib2 import HTTPPasswordMgrWithDefaultRealm, HTTPBasicAuthHandler, Request, build_opener
  from urllib import urlencode


def curl(url, params=None, auth=None, req_type="GET", data=None, headers=None):
  post_req = ["POST", "PUT"]
  get_req = ["GET", "DELETE"]

  if params is not None:
    url += "?" + urlencode(params)

  if req_type not in post_req + get_req:
    raise IOError("Wrong request type \"%s\" passed" % req_type)

  _headers = {}
  handler_chain = []

  if auth is not None:
    manager = HTTPPasswordMgrWithDefaultRealm()
    manager.add_password(None, url, auth["user"], auth["pass"])
    handler_chain.append(HTTPBasicAuthHandler(manager))

  if req_type in post_req and data is not None:
    _headers["Content-Length"] = len(data)

  if headers is not None:
    _headers.update(headers)

  director = build_opener(*handler_chain)

  if req_type in post_req:
    if sys.version_info.major == 3:
      _data = bytes(data, encoding='utf8')
    else:
      _data = bytes(data)

    req = Request(url, headers=_headers, data=_data)
  else:
    req = Request(url, headers=_headers)

  req.get_method = lambda: req_type
  result = director.open(req)

  return {
    "httpcode": result.code,
    "headers": result.info(),
    "content": result.read()
  }


"""
Usage example:
"""

Post data:
  curl("http://127.0.0.1/", req_type="POST", data='cascac')

Pass arguments (http://127.0.0.1/?q=show):
  curl("http://127.0.0.1/", params={'q': 'show'}, req_type="POST", data='cascac')

HTTP Authorization:
  curl("http://127.0.0.1/secure_data.txt", auth={"user": "username", "pass": "password"})

ฟังก์ชั่นไม่สมบูรณ์และอาจไม่เหมาะ แต่แสดงการแสดงพื้นฐานและแนวคิดที่จะใช้ สิ่งเพิ่มเติมสามารถเพิ่มหรือเปลี่ยนแปลงได้ตามรสนิยม

อัปเดต 12/08

นี่คือลิงก์ GitHub ไปยังแหล่งที่อัปเดตแบบสด กำลังสนับสนุน:

  • การอนุญาต

  • รองรับ CRUD

  • การตรวจจับชุดอักขระอัตโนมัติ

  • การเข้ารหัสอัตโนมัติ (การบีบอัด) การตรวจจับ


4

หากทำงานทั้งหมดข้างต้นจากบรรทัดคำสั่งที่คุณต้องการฉันขอแนะนำ HTTPie เป็นทางเลือก cURL ที่ยอดเยี่ยมและใช้งานง่ายและสะดวกสุด ๆ(และปรับแต่งเอง)

นี่คือคำอธิบาย(รวบรัดและแม่นยำ)จาก GitHub

HTTPie (ออกเสียงว่า aych-tee-tee-pie) เป็นไคลเอนต์ HTTP บรรทัดคำสั่ง เป้าหมายคือการทำให้ CLI ปฏิสัมพันธ์กับบริการเว็บเป็นมิตรกับมนุษย์มากที่สุด

มีคำสั่ง http ง่ายๆที่อนุญาตให้ส่งคำขอ HTTP โดยพลการโดยใช้ไวยากรณ์ที่เรียบง่ายและเป็นธรรมชาติและแสดงเอาต์พุตที่เป็นสี HTTPie สามารถใช้สำหรับการทดสอบการดีบักและโดยทั่วไปโต้ตอบกับเซิร์ฟเวอร์ HTTP


เอกสารเกี่ยวกับการรับรองความถูกต้องควรให้คำแนะนำที่เพียงพอแก่คุณในการแก้ปัญหาของคุณ แน่นอนว่าคำตอบทั้งหมดข้างต้นนั้นถูกต้องเช่นกันและมีวิธีต่างๆในการทำงานเดียวกันให้สำเร็จ


ดังนั้นคุณไม่จำเป็นต้องย้ายออกจาก Stack Overflow นี่คือสิ่งที่มีให้โดยสรุป

Basic auth:

$ http -a username:password example.org
Digest auth:

$ http --auth-type=digest -a username:password example.org
With password prompt:

$ http -a username example.org


บางทีฉันอาจไม่เข้าใจเลย แต่มันเป็นโมดูล Python หรือไม่ ฉันเดาว่ามันเป็นเครื่องมือของเชลล์ / CLI และฉันก็ผิดหวัง: '(ดูเหมือนจะใช้งานง่ายมาก
Alex

@ Alex - เป็นโมดูล Python README บน Github ( github.com/jkbrzt/httpie ) มีทุกสิ่งที่คุณต้องการ
stuxnetting
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.