ошибка ascii в python, сериализующем файл для SOAP

Я работаю над мыльной оболочкой для API (я знаю, что REST существует... это проект в моей работе), для этого я использую библиотеку SUDS.

Я нашел этот вопрос, и ответ помог мне много. Попробовав пару вещей и немного изменив скрипт, на который мне указал этот вопрос, я получил следующую ошибку:

UnicodeDecodeError: 'ascii' codec can't decode byte 0x82 in position 2159: ordinal not in range(128)

Это происходит при отправке запроса на конечную точку SOAP. Я пытался использовать unicodedata с параметром NFKD для его нормализации, но все равно получаю те же ошибки.

Поскольку это не простой текст, это фактические данные из аудиофайла, я не уверен, но предполагаю, что его изменение должно повредить фактические данные, поэтому я не знаю, что здесь делать.

Это то, что я делаю, это не слишком отличается от процедуры в другом вопросе:

file = open('path/to/the/file.mp3', 'rb')
mime_type = 'audio/mpeg'
audio_data = file.read()
bin_param = (audio_data, uuid.uuid4(), mime_type)

with_soap_attachment(client.service.set_greeting, bin_param, request_data)

Скрипт, насколько я понял, преобразует все входные аргументы в строку сообщения SOAP, а затем инкапсулирует его в объект запроса и отправляет в конечную точку SOAP, поэтому проблема в том, что audio_data содержит недопустимые символы ascii.

Любая подсказка здесь?

РЕДАКТИРОВАНИЕ: 04.04.2013

Вот собственно код обёртки

#coding: utf-8
from suds.transport import Request
import re
import uuid

def with_soap_attachment(suds_method, attachment_data, soap_location, *args, **kwargs):
    MIME_DEFAULT = 'text/plain'
    attachment_transfer_encoding = 'binary'
    soap_method = suds_method.method

    if len(attachment_data) == 3:
        data, attachment_id, attachment_mimetype = attachment_data
    elif len(attachment_data) == 2:
        data, attachment_mimetype = attachment_data
        attachment_id = uuid.uuid4()
    elif len(attachment_data) == 1:
        data = attachment_data
        attachment_mimetype = MIME_DEFAULT
        attachment_id = uuid.uuid4()

    soap_client = suds_method.clientclass(kwargs)
    binding = soap_method.binding.input
    soap_xml = binding.get_message(soap_method, args, kwargs)

    boundary_id = 'uuid:%s' % uuid.uuid4()
    root_part_id ='uuid:%s' % uuid.uuid4()
    request_headers = {
      'Content-Type': '; '.join([
          'multipart/related',
          'type="text/xml"',
          'start="<%s>"' % root_part_id,
          'boundary="%s"' % boundary_id,
        ]),
    }
    soap_headers = '\n'.join([
      'Content-Type: text/xml; charset=UTF-8',
      'Content-Transfer-Encoding: 8bit',
      'Content-Id: <%s>' % root_part_id,
      '',
    ])
    attachment_headers = '\n'.join([
      'Content-Type: %s' % attachment_mimetype,
      'Content-Transfer-Encoding: %s' % attachment_transfer_encoding,
      'Content-Id: <%s>' % attachment_id,
      '',
    ])

    request_text = '\n'.join([
      '',
      '--%s' % boundary_id,
      soap_headers,
      unicode(soap_xml),
      '--%s' % boundary_id,
      attachment_headers,
      data,
      '--%s--' % boundary_id
    ])

    location = soap_location

    headers = suds_method.client.options.headers.copy()
    headers.update(request_headers)
    request = Request(location, request_text)
    request.headers = headers

    response = suds_method.client.options.transport.send(request)
    return response

Вот вся трассировка

---------------------------------------------------------------------------
UnicodeDecodeError                        Traceback (most recent call last)
/home/israelord/.virtualenvs/ringtu-env/local/lib/python2.7/site-packages/django/core/management/commands/shell.pyc in <module>()
----> 1 soap_attachments.with_soap_attachment(service.set_menu_prompt, bin_param, AUTOATTENDANT_ENDPOINT, request)

/home/israelord/Work/4geeks/ringtu/ringtu/services/soap_attachments.py in with_soap_attachment(suds_method, attachment_data, soap_location, *args, **kwargs)
     54       attachment_headers,
     55       data,
---> 56       '--%s--' % boundary_id
     57     ])
     58 

UnicodeDecodeError: 'ascii' codec can't decode byte 0x82 in position 148: ordinal not in range(128)

person iferminm    schedule 02.04.2013    source источник
comment
попробуйте заменить audio_data = file.read() на audio_data = file.read().encode('utf8'). Посмотрите, работает ли это.   -  person Ionut Hulub    schedule 02.04.2013
comment
@IonutHulub file.read() уже возвращает str.   -  person wRAR    schedule 02.04.2013
comment
@wRAR Ты не говоришь? функция encode('utf8') кодирует строку, чтобы кодек 'ascii' мог ее декодировать. Меня беспокоит только то, что данные будут повреждены и станут неинтерпретируемыми для последующего использования.   -  person Ionut Hulub    schedule 02.04.2013
comment
@IonutHulub, ты не понимаешь, что делает encode.   -  person wRAR    schedule 02.04.2013


Ответы (1)


Что ж, оболочка не поддерживает бинарные файлы, так как использует только Content-Transfer-Encoding: 8bit, что, конечно же, не может работать с бинарными файлами. Вам, вероятно, потребуется изменить его в соответствии со спецификацией SOAP-вложений.

person wRAR    schedule 02.04.2013
comment
Спасибо за ваше предложение, я попробовал то, что @lonutHulub сказал раньше, в одной из этих отчаянных попыток, но это явно не сработало. Я не получаю сообщение об ошибке передачи с сервера, потому что запрос никогда не отправляется из-за ошибки кодирования. - person iferminm; 02.04.2013
comment
Есть ли у вас какие-либо предложения о том, как решить проблему с кодировкой? - person iferminm; 02.04.2013
comment
Да, мне нужно реализовать это вручную, я изменил Content-Transfer-Encodinf с 8-битного на двоичный в заголовке вложения и оставил его 8-битным в заголовке Soap, как описано здесь w3.org/TR/SOAP-attachments, большое спасибо за это, но я все равно получаю ошибку кодирования. - person iferminm; 02.04.2013
comment
@israelord попробуйте добавить в файл комментарий coding: utf-8, так как проблема, по-видимому, вызвана объединением двоичных данных с литералом '\n', который по умолчанию является ascii. - person wRAR; 02.04.2013
comment
Привет, файл уже имеет заголовок комментария #coding: utf-8. Проблема в самих данных, я их отлаживал, и проблема в том, что они просто конкатенируют переменную данных, содержащую байты из mp3-файла. Я обновил свой вопрос, указав фактический код оболочки. Большое Вам спасибо - person iferminm; 04.04.2013
comment
@israelord проблема не в данных, а в кодировке, используемой для их декодирования в unicode. Вы уверены, что заголовок присутствует в файле с оберткой? - person wRAR; 04.04.2013
comment
from __future__ import unicode_literals — это третья ошибка, если вы добавили ее сами. - person wRAR; 04.04.2013
comment
Все еще получаю ту же ошибку, я только что обновил код до фактического состояния, большое спасибо за вашу помощь. - person iferminm; 04.04.2013
comment
Я только что заметил этот unicode(soap_xml) предмет. Этот код довольно плохой, так как он смешивает переменные str и unicode. Вам нужно сделать все эти переменные и литералы str или unicode в зависимости от того, каким должен быть результат, который передается в Request. - person wRAR; 04.04.2013
comment
да, раньше это была str(soap_xml), и партнер предложил изменить ее таким образом. Я проверю параметры запроса. - person iferminm; 04.04.2013
comment
Чувак, я заставил это работать, у меня была функция предварительной обработки некоторых данных, и она возвращала объект юникода, и в этом была проблема. Большое спасибо! - person iferminm; 04.04.2013