использование модуля urllib3 вместо запросов в python - PullRequest
1 голос
/ 02 апреля 2020

Этот код работает правильно в версии python 2.X. Я пытаюсь использовать подобный код в python версии 3. Проблема в том, что я не хочу использовать модуль запросов. Мне нужно, чтобы он работал, используя "urllib3".

import requests
import urllib

event = {'url':'http://google.com', 'email':'abc@gmail.com', 'title':'test'}

url = event['url']
if event['email']:
    email=event['email']

if event['title']:
    title=event['title']

url1 = urllib.parse.unquote(url)
myfile=urllib.request.urlopen(url1)

requests.post("https://api.mailgun.net/v3/xxx.mailgun.org/messages",
                    auth=("api", "key-xxx"),
                    files=[("attachment", myfile)
                           ],
                    data={"from": "Excited User <excited-user@example.com>",
                          "to": email,
                          "subject": title,
                          "text": "Testing some awesomness with attachments!",
                          "html": myfile})

Я получаю TypeError при попытке запустить этот код:

import urllib3

event = {'url':'http://oksoft.blogspot.com', 'email':'abc@gmail.com', 'title':'test'}

url = event['url']
if event['email']:
    email=event['email']

if event['title']:
    title=event['title']

url1 = urllib.parse.unquote(url)
myfile=urllib.request.urlopen(url1)

http = urllib3.PoolManager()
url = "https://api.mailgun.net/v3/xxx.mailgun.org/messages"

params={"from": "Excited User <excited-user@example.com>",
                          "to": email,
                          "subject": title,
                          "text": "Testing some awesomness with attachments!",
                          "html": myfile} 

http.request(
    "POST", url, headers={"Content-Type": "application/json", "api":"key-xxx"}, body= params
)

Ответы [ 2 ]

1 голос
/ 05 апреля 2020

Этот код использует модуль urllib.reqeust. Фактически создать файл attachment в отличие от inline html content немного сложнее, чем установка параметра html для содержимого файла.

import urllib.request
import urllib.error
import urllib.parse

import io
import mimetypes
import uuid

class MultiPartForm:
    """Accumulate the data to be used when posting a form."""

    def __init__(self):
        self.form_fields = []
        self.files = []
        # Use a large random byte string to separate
        # parts of the MIME data.
        self.boundary = uuid.uuid4().hex.encode('utf-8')
        return

    def get_content_type(self):
        return 'multipart/form-data; boundary={}'.format(
            self.boundary.decode('utf-8'))

    def add_field(self, name, value):
        """Add a simple field to the form data."""
        self.form_fields.append((name, value))

    def add_file(self, fieldname, filename, fileHandle,
                 mimetype=None):
        """Add a file to be uploaded."""
        body = fileHandle.read()
        if mimetype is None:
            mimetype = (
                mimetypes.guess_type(filename)[0] or
                'application/octet-stream'
            )
        self.files.append((fieldname, filename, mimetype, body))
        return

    @staticmethod
    def _form_data(name):
        return ('Content-Disposition: form-data; '
                'name="{}"\r\n').format(name).encode('utf-8')

    @staticmethod
    def _attached_file(name, filename):
        return ('Content-Disposition: file; '
                'name="{}"; filename="{}"\r\n').format(
                    name, filename).encode('utf-8')

    @staticmethod
    def _content_type(ct):
        return 'Content-Type: {}\r\n'.format(ct).encode('utf-8')

    def __bytes__(self):
        """Return a byte-string representing the form data,
        including attached files.
        """
        buffer = io.BytesIO()
        boundary = b'--' + self.boundary + b'\r\n'

        # Add the form fields
        for name, value in self.form_fields:
            buffer.write(boundary)
            buffer.write(self._form_data(name))
            buffer.write(b'\r\n')
            buffer.write(value.encode('utf-8'))
            buffer.write(b'\r\n')

        # Add the files to upload
        for f_name, filename, f_content_type, body in self.files:
            buffer.write(boundary)
            buffer.write(self._attached_file(f_name, filename))
            buffer.write(self._content_type(f_content_type))
            buffer.write(b'\r\n')
            buffer.write(body)
            buffer.write(b'\r\n')

        buffer.write(b'--' + self.boundary + b'--\r\n')
        return buffer.getvalue()


event = {'url':'http://oksoft.blogspot.com', 'email':'abc@gmail.com', 'title':'test'}

url = event['url']
if event['email']:
    email=event['email']

if event['title']:
    title=event['title']

form = MultiPartForm()
form.add_field("from", "Excited User <excited-user@example.com>")
form.add_field("to", email)
form.add_field("subject", title)
form.add_field("text", "Testing some awesomness with attachments!")
with urllib.request.urlopen(url) as f:
    form.add_file("attachment", "test.html", f, "text/html")

url = "https://api.mailgun.net/v3/xxx.mailgun.org/messages"

# create basic authorization opener
auth_handler = urllib.request.HTTPBasicAuthHandler()
auth_handler.add_password(realm='MG API',
                          uri=url,
                          user='api',
                          passwd='xxx-key')
opener = urllib.request.build_opener(auth_handler)

data = bytes(form)
req = urllib.request.Request(url, data=data)
req.add_header('Content-type', form.get_content_type())
req.add_header('Content-length', len(data))
with opener.open(req) as f:
     print(f.read().decode('utf-8'))
1 голос
/ 04 апреля 2020

Возвращает TypeError: can't concat str to bytes, потому что ваш myfile имеет тип http.client.HTTPResponse, а не тип str - который должен быть передан в тело запроса.

Итак, сначала нужно преобразовать ответ в строку, а затем json -сериализировать тело params.


Полный код:

import urllib3
import urllib.request
import urllib.parse
import json

event = {'url': 'http://oksoft.blogspot.com',
         'email': 'abc@gmail.com', 'title': 'test'}

url = event['url']
if event['email']:
    email = event['email']

if event['title']:
    title = event['title']

url1 = urllib.parse.unquote(url)
myfile = urllib.request.urlopen(url1)

myfile_content = myfile.read()\
    .decode(myfile.headers
            .get_content_charset(failobj='utf-8'))

http = urllib3.PoolManager()
url = "https://api.mailgun.net/v3/xxx.mailgun.org/messages"

params = {"from": "Excited User <excited-user@example.com>",
          "to": email,
          "subject": title,
          "text": "Testing some awesomness with attachments!",
          "html": myfile_content}

### EDIT

auth_headers = urllib3.util.make_headers(
    basic_auth='api:xxx')

r = http.request(
    "POST",
    url,
    headers=auth_headers,
    fields=params
)

print(r.status, r.data)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...