How can I solve this without making too much of a dog's dinner of code that started out small and elegant?
К сожалению, существует несколько дополнительных шагов, необходимых для предотвращения ошибок декодирования/кодирования. python 2.x имеет множество мест, где неявный кодирования/декодирования, т. е. за вашей спиной и без вашего разрешения. Когда python выполняет неявное кодирование/декодирование, он использует ascii-кодек, что приведет к ошибке кодирования/декодирования, если присутствует символ utf-8 (или любой другой не-ascii). В результате вы должны найти все места, где python выполняет неявные кодировки/декодирования и заменять их явными кодировками/декодированием - если вы хотите, чтобы ваша программа обрабатывала символы не-ascii в этих местах.
По крайней мере, любой вход внешнего источника должен быть декодирован в строку юникода перед продолжением, что означает, что вам нужно знать кодировку ввода.Но если объединить Юникод строку с регулярными строками, вы можете получить ошибки кодирования/декодирования, например:
#-*- coding: utf-8 -*- #Allows utf-8 characters in your source code
unicode_str = '€'.decode('utf-8')
my_str = '{0}{1}'.format('This is the Euro sign: ', unicode_str)
--output:--
Traceback (most recent call last):
File "1.py", line 3, in <module>
my_str = '{0}{1}'.format('hello', unicode_str)
UnicodeEncodeError: 'ascii' codec can't encode character u'\u20ac' in position 0: ordinal not in range(128)
Поэтому все ваши строки, вероятно, должны быть расшифрованы в юникоде строки. Затем, когда вы хотите вывести строки, вам нужно закодировать строки юникода.
import sys
import json
import codecs
import urllib
def printDict(d, path, filename):
for key, val in d.items(): #key is a unicode string, val is a unicode string or dict
if isinstance(val, dict):
printDict(
val,
u'{0}{1}/'.format(path, key), #format() specifiers require 0,1 for python 2.6
filename
)
else:
key_str = key.encode('utf-8')
val_str = val.encode('utf-8')
url = '{0}{1}{2} -d "{3}"'.format(
filename,
path,
key_str,
val_str
)
print url
url_escaped = urllib.quote(url)
print url_escaped
curl_cmd = 'curl -X PUT'
base_url = 'http://localhost:8500/v1/kv/'
print "{0} {1}{2}".format(curl_cmd, base_url, url_escaped)
filename = sys.argv[1].decode('utf-8')
file_encoding = 'utf-8'
fh = codecs.open(filename, encoding=file_encoding)
my_json = json.load(fh)
fh.close()
print my_json
path = "/"
printDict(my_json, path.decode('utf-8'), filename) #Can the path have non-ascii characters in it?
--output:--
{u'FacetConfig': {u'facet:price-lf-p': {u'prefixParts': u'\xa3'}}}
data.txt/FacetConfig/facet:price-lf-p/prefixParts -d "£"
data.txt/FacetConfig/facet%3Aprice-lf-p/prefixParts%20-d%20%22%C2%A3%22
curl -X PUT http://localhost:8500/v1/kv/data.txt/FacetConfig/facet%3Aprice-lf-p/prefixParts%20-d%20%22%C2%A3%22
Хм, это d [ключ], который содержит знак волшебства, однако я получаю более драматичную ошибку: AttributeError: объект 'module' не имеет атрибута 'urlquote' – gdhgdh
@gdhgdh: right, typo с моей стороны. Вы по-прежнему хотите правильно закодировать свой URL. –
Я потратил немного времени, чтобы на самом деле прочитать ошибку и заметил, что это еще одна часть кода, поэтому я удалил следующий вопрос. Спасибо, что ответили все равно! :) – gdhgdh