LINUX.ORG.RU

UTF-8 в Python

 , ,


1

3

Да, опять. Нихрена не работает.

js'ом отправляю сериализованную форму в которой только одно поле - имя под которым нужно сохранить файл. Получю файл сохранянный с именем вроде «\xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb». Как с этим бороться?

Всякие

# -*- coding: utf-8 -*- from __future__ import unicode_literals
и
import sys
reload(sys)
sys.setdefaultencoding('utf8')
уже попробовал. Тем более как я понял это только для данных в файле скрипта актуально.

Пытался тупо перебрать варианты (в консоль оно так же пишет бред):

print(listName.decode('utf-8'))
		print(listName.encode('utf-8'))
		print(listName.decode())
		print(listName.encode())
C нулевым результатом.

★★★★★

Последнее исправление: CYB3R (всего исправлений: 1)

Ответ на: комментарий от ass

Было бы неплохо получить общее решение для 2.7 и 3. Но это 2.7, так как скрипт вообще еще не пашет в 3 - нужны будут правки, а я до этого еще не добрался.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от MyTrooName

Абсолютно то же самое. Может проблема еще при разборе параметров. Я не уверен. Это первый мой опыт с python - пытаюсь переписать вэб-интерфейс для Cementine. Уже перетащил на ajax, много чего выправил. А вот эту траблу не могу решить (это сохранение плейлиста). Оно и в оригинале так работало разумеется.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic
>>> a = 'фыва'
>>> a.decode('utf-8')
u'\u0444\u044b\u0432\u0430'
>>> a.encode('utf-8')
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
UnicodeDecodeError: 'ascii' codec can't decode byte 0xd1 in position 0: ordinal not in range(128)
>>> type(a)
<type 'str'>
>>> 

где наврал?

MyTrooName ★★★★★
()
Ответ на: комментарий от MyTrooName

ну, с setsystemencoding exception не вылетит, но результат все равно отличается

MyTrooName ★★★★★
()

это -*- coding: utf-8 и это reload(sys) sys.setdefaultencoding('utf8') - не нужно

py3:


s = get_text_with_some_code()

txt = None
if isinstance(s, bytes):
    txt = str(s, 'utf-8')
elif isinstance(s, str):
    txt = s
else:
    do_something_else()

py2:


s = get_text_with_some_code()

txt = None
if isinstance(s, str):
    txt = unicode(s, 'utf-8')
elif isinstance(s, unicode):
    txt = s
else:
    do_something_else()

благодарности присылать сюда https://vk.com/id51539439

anonymous
()
Ответ на: комментарий от anonymous

а вот универсальный код (для py3 и py2):

unicode_t = str if not hasattr(__builtins__, 'unicode') else unicode

s = get_text_with_some_code()

txt = None
if isinstance(s, unicode_t):
    txt = s
elif isinstance(s, bytes):
    txt = s.decode('utf-8')
else:
    do_something_else()

благодарности присылать не надо :-)

user_id_68054 ★★★★★
()

О, пляски с бубном. Как мило. Что за фреймворк? Ты уверен что приложение крутится под правильной локалью?

bj
()
Ответ на: комментарий от bj

__builtins__ лучше не использовать.

почему?

ну и ... быть может — тогда уж и старенький python2 лучше не использовать? :-)

И вообще getattr(__builtins__, 'unicode', str)

круть! да :-)

user_id_68054 ★★★★★
()
Последнее исправление: user_id_68054 (всего исправлений: 3)
Ответ на: комментарий от bj

__builtins__ лучше не использовать

тогда предлагаю на обсуждение ещё вариант:

unicode_t = str if str is not bytes else unicode

s = get_text_with_some_code()

txt = None
if isinstance(s, unicode_t):
    txt = s
elif isinstance(s, bytes):
    txt = s.decode('utf-8')
else:
    do_something_else()
user_id_68054 ★★★★★
()
Последнее исправление: user_id_68054 (всего исправлений: 2)
Ответ на: комментарий от user_id_68054

почему?

The value of __builtins__ is normally either this module or the value of this modules’s __dict__ attribute.

bj
()
Ответ на: комментарий от user_id_68054

Это все не имеет смысла, так как проблема ТС в другом. 70% что у него косые данные приходят от клиента.

bj
()
Ответ на: комментарий от bj

ещё думаю проблема что ТС в том что у него несколько проблем, а он возможно считает что проблема только одна

user_id_68054 ★★★★★
()
echo $LANG
locale -a
mount | grep charset

на каком разделе создается файл?

что выводит print(listName)?

ei-grad ★★★★★
()
Ответ на: комментарий от user_id_68054

благодарности присылать не надо :-)

конечно не надо, вед.

[#]у тебя баг в коде [#]это костыль

anonymous
()
Ответ на: комментарий от ei-grad
[02:36:28] alex@alex-desktop /home/alex (1)                                                                                                                                                                    
> echo $LANG
ru_RU.UTF-8
[02:38:19] alex@alex-desktop /home/alex (0)                                                                                                                                                                    
> locale -a
C
C.UTF-8
en_AG
en_AG.utf8
en_AU.utf8
en_BW.utf8
en_CA.utf8
en_DK.utf8
en_GB.utf8
en_HK.utf8
en_IE.utf8
en_IN
en_IN.utf8
en_NG
en_NG.utf8
en_NZ.utf8
en_PH.utf8
en_SG.utf8
en_US.utf8
en_ZA.utf8
en_ZM
en_ZM.utf8
en_ZW.utf8
POSIX
ru_RU.utf8
ru_UA.utf8
Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от user_id_68054

И тоже нет. Ни один из рецептов не помог.

Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от bj

Что значит «косые данные приходят от клиента». Всем не косые, а python персонально косые? И даже если это так, что с этим делать? Утилита как бы общего назначения и должна работать везде, в том числе и если клиент косой на оба глаза.

Вот парсинг POST (просто слямзил откуда-то):

#!/usr/bin/env python
# -*- coding: utf-8 -*- from __future__ import unicode_literals

#    This program is free software: you can redistribute it and/or modify
#    it under the terms of the GNU General Public License as published by
#    the Free Software Foundation, either version 3 of the License, or
#    (at your option) any later version.

#    This program is distributed in the hope that it will be useful,
#    but WITHOUT ANY WARRANTY; without even the implied warranty of
#    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
#    GNU General Public License for more details.

#    You should have received a copy of the GNU General Public License
#    along with this program.  If not, see <http://www.gnu.org/licenses/>.

#import urlparse
#import getopt
#import sys

import sys
reload(sys)
sys.setdefaultencoding('utf8')

from sys import version as python_version
from cgi import parse_header, parse_multipart
if python_version.startswith('3'):
	from urllib.parse import parse_qs
	from http.server import BaseHTTPRequestHandler
else:
	from urlparse import parse_qs

import BaseHTTPServer
import clementineDriver as Clementine
import web as Web
import functionality as Functionality
import config

#import os

class RequestHandler (BaseHTTPServer.BaseHTTPRequestHandler):
	
		
	def do_POST (self):
		print '================================= Request ===================================';
		ctype, pdict = parse_header(self.headers.getheader("content-type"))
		actionCode = '--'
		
		if ctype == 'multipart/form-data':
			postvars = parse_multipart(self.rfile, pdict)
		elif ctype == 'application/x-www-form-urlencoded':
			length = int(self.headers.getheader('content-length'))
			postvars = parse_qs(self.rfile.read(length), keep_blank_values=1)
		else:
			postvars = {}
		
		self.web = None
		self.web = Web.Web()
		if self.connectToClementine():
			backend = Functionality.Functionality(self.path,self.clementine)
		
			if 'action' in postvars:
				actionCode = self.cleanParameter(postvars['action'])
				print 'action: '+actionCode
				if 'value' in postvars:
					actionValue = self.cleanParameter(postvars['value'])
				else:
					actionValue = 0
				print 'value: '+actionValue
				result = backend.actionRun(actionCode, actionValue)
			else:
				result = 'noaction'
				
			self.web.reply(self.wfile,self.clementine,backend,result)
		else:
			self.wfile.write('disconnect')
		
		return
Suntechnic ★★★★★
() автор топика
Ответ на: комментарий от Suntechnic

Да, мне очень не нравится этот кустарный веб-сервер. Почему бы не взять что-то вроде web.py, Bottle, CherryPy?

Deleted
()
Ответ на: комментарий от Deleted

Да, блин чо было, то и взял. Я там по большому счету добавил только do_POST. Первый раз python вижу...

Ну и перепилил web на отдачу json чтобы все по ajax работало, да починил отдачу ресурсов. И выкорчевал html из кода в отдельный html-файл. Сейчас еще переверстаю, чтобы мне для телика подходило и это будет все что мне от него надо ;)

По-хорошему бы выправить конечно python код. JS я вылижу наверно. А дальше... Ну если кому-то будет будет не лень - вэлком, так сказать.

Suntechnic ★★★★★
() автор топика

Чем ты его парсишь? Самописные парсер? И да, нодо понимать разницу между str (как массивом байт), str(как строкой) и unicode(как строкой). Не стоит к строкам относится как к масивам байт, относись как к масивам глифов, хотя там еще не факт, что поддерживаются группы

namezys ★★★★
()
Последнее исправление: namezys (всего исправлений: 1)

\xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb - это не Юникод. Юникод в Питоне вот такой:

>>> str = u"Проверка"
>>> print str
Проверка
>>> str
u'\u041f\u0440\u043e\u0432\u0435\u0440\u043a\u0430'

menangen ★★★★★
()
Ответ на: комментарий от Suntechnic

У тебя херь в cleanParameters. Ты приводишь список с параметром к строке str(['буу']), а потом удаляешь квадратные скобки. Естественно строка у тебя как после repr.

parse_qs: Data are returned as a dictionary. The dictionary keys are the unique query variable names and the values are lists of values for each name.

the values are lists of values for each name.

lists of values

bj
()
Ответ на: комментарий от menangen

Ты никогда бабку не догонишь, с костылями то.

bj
()
>>> print "\xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb"
файл
>>> source = open("\xd1\x84\xd0\xb0\xd0\xb9\xd0\xbb", "w")
>>> source.write("hello?")
>>> source.close()
>>> source = open("файл", "r")
>>> source.read(6)
hello?

Если так сильно напрягает, ставь https://github.com/moskytw/uniout.

vertinsky
()
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.