Ошибка при наличии неанглийских символов [дублировать]

Попробуйте

<?php
$to = "somebody@example.com, somebodyelse@example.com";
$subject = "HTML email";

$message = "
    <html>
    <head>
       <title>HTML email</title>
    </head>
    <body>
      <p>This email contains HTML Tags!</p>
      <table>
        <tr>
         <th>Firstname</th>
         <th>Lastname</th>
        </tr>
        <tr>
          <td>John</td>
          <td>Doe</td>
        </tr>
      </table>
    </body>
    </html>";

// Always set content-type when sending HTML email
$headers = "MIME-Version: 1.0" . "\r\n";
$headers .= "Content-type:text/html;charset=UTF-8" . "\r\n";

// More headers
$headers .= 'From: <webmaster@example.com>' . "\r\n";
$headers .= 'Cc: myboss@example.com' . "\r\n";

mail($to,$subject,$message,$headers);
?> 
188
задан Aaron Hall 13 May 2016 в 21:29
поделиться

7 ответов

Исключительно используйте объекты unicode как можно больше, расшифровывая объекты для unicode-объектов, когда вы их сначала получаете и кодируете по мере необходимости.

Если ваша строка на самом деле является объектом unicode, вы нужно будет преобразовать его в строковый объект, закодированный в кодировке unicode, прежде чем записывать его в файл:

foo = u'Δ, Й, ק, ‎ م, ๗, あ, 叶, 葉, and 말.'
f = open('test', 'w')
f.write(foo.encode('utf8'))
f.close()

Когда вы снова прочтете этот файл, вы получите строку с кодировкой в ​​кодировке Юникода, которую вы можете декодировать к объекту unicode:

f = file('test', 'r')
print f.read().decode('utf8')
282
ответ дан quasistoic 22 August 2018 в 15:37
поделиться
  • 1
    Благодарю. Это выполняется без ошибок, но затем, если я открою текстовый файл, я вижу кучу странных символов :) Мне нужно скопировать и вставить текст на страницу Wordpress (не спрашивайте). Есть ли способ опубликовать символы, которые есть там? Я думаю, что не для txt-файла, но, может быть, для чего-то еще? – simon 18 May 2011 в 17:55
  • 2
    Что вы используете для открытия текстового файла? Я предполагаю, что вы в Windows, и вы открываете его в «Блокноте», который не слишком умен с кодировками. Что происходит, когда вы открываете его в Wordpad? – quasistoic 18 May 2011 в 18:37

Предисловие: будет ли ваш просмотрщик работать?

Убедитесь, что ваш просмотрщик / редактор / терминал (однако вы взаимодействуете с вашим файлом, закодированным в utf-8) можете прочитать файл. Это часто возникает в Windows , например, «Блокнот».

Написание текста в текстовом файле в формате Unicode?

In Python 2, используйте open из модуля io (это то же самое, что встроенный open в Python 3):

import io

Лучшая практика, в общем, использует UTF-8 для

encoding = 'utf-8'

utf-8 - это самая современная и универсально используемая кодировка - она ​​работает во всех веб-браузерах , большинство текстовых редакторов (см. ваши настройки, если у вас есть проблемы) и большинство терминалов / оболочек.

В Windows вы можете попробовать utf-16le, если вы ограничены просмотром вывода в Блокноте (или другом ограниченном viewer).

encoding = 'utf-16le' # sorry, Windows users... :(

И просто откройте его с помощью диспетчера контекстов и напишите символы юникода:

with io.open(filename, 'w', encoding=encoding) as f:
    f.write(unicode_object)

Пример использования многих символов Юникода

Вот пример, который пытается сопоставить все возможные символы шириной до трех бит (4 - макс, но это будет немного далеко) от цифрового r epresentation (в целых числах) к выходу с кодированной печатаемой записью вместе с ее именем (поместите это в файл с именем uni.py):

from __future__ import print_function
import io
from unicodedata import name, category
from curses.ascii import controlnames
from collections import Counter

try: # use these if Python 2
    unicode_chr, range = unichr, xrange
except NameError: # Python 3
    unicode_chr = chr

exclude_categories = set(('Co', 'Cn'))
counts = Counter()
control_names = dict(enumerate(controlnames))
with io.open('unidata', 'w', encoding='utf-8') as f:
    for x in range((2**8)**3): 
        try:
            char = unicode_chr(x)
        except ValueError:
            continue # can't map to unicode, try next x
        cat = category(char)
        counts.update((cat,))
        if cat in exclude_categories:
            continue # get rid of noise & greatly shorten result file
        try:
            uname = name(char)
        except ValueError: # probably control character, don't use actual
            uname = control_names.get(x, '')
            f.write(u'{0:>6x} {1}    {2}\n'.format(x, cat, uname))
        else:
            f.write(u'{0:>6x} {1}  {2}  {3}\n'.format(x, cat, char, uname))
# may as well describe the types we logged.
for cat, count in counts.items():
    print('{0} chars of category, {1}'.format(count, cat))

Это должно выполняться примерно в минуту , и вы можете просмотреть файл данных, и если ваш просмотрщик файлов может отображать unicode, вы увидите его. Информацию о категориях можно найти здесь здесь . Основываясь на подсчетах, мы, вероятно, можем улучшить наши результаты, исключив категории Cn и Co, у которых нет связанных с ними символов.

$ python uni.py

Будет отображено шестнадцатеричное отображение, category , символ (если не удается получить имя, возможно, контрольный символ) и имя символа. например,

Я рекомендую less в Unix или Cygwin (не печатайте / не копируйте весь файл на ваш выход):

$ less unidata

, например. будет отображаться аналогично следующим строкам, которые я выбрал из него, используя Python 2 (unicode 5.2):

     0 Cc NUL
    20 Zs     SPACE
    21 Po  !  EXCLAMATION MARK
    b6 So  ¶  PILCROW SIGN
    d0 Lu  Ð  LATIN CAPITAL LETTER ETH
   e59 Nd  ๙  THAI DIGIT NINE
  2887 So  ⢇  BRAILLE PATTERN DOTS-1238
  bc13 Lo  밓  HANGUL SYLLABLE MIH
  ffeb Sm  →  HALFWIDTH RIGHTWARDS ARROW

My Python 3.5 из Anaconda имеет unicode 8.0, я бы предположил, что большинство 3 будет.

13
ответ дан Aaron Hall 22 August 2018 в 15:37
поделиться

Как печатать символы Unicode в файл:

Сохранить это в файле: foo.py:

#!/usr/bin/python -tt
# -*- coding: utf-8 -*-
import codecs
import sys 
UTF8Writer = codecs.getwriter('utf8')
sys.stdout = UTF8Writer(sys.stdout)
print(u'e with obfuscation: é')

Запустить его и вывести канал в файл:

python foo.py > tmp.txt

Откройте tmp.txt и загляните внутрь, вы увидите следующее:

el@apollo:~$ cat tmp.txt 
e with obfuscation: é

Таким образом, вы сохранили unicode e с отметкой обфускации на нем в файл.

3
ответ дан Eric Leschinski 22 August 2018 в 15:37
поделиться
  • 1
    Я был очень взволнован этим ответом, но это дает ошибку на моей машине. Когда я копирую / вставляю код, я получаю сообщение об ошибке: & quot; TypeError: должен быть str, а не байтами & quot; – Richard Rast 6 March 2014 в 02:05

В Python 2.6+ вы можете использовать io.open() , который по умолчанию ( builtin open() ) на Python 3:

import io

with io.open(filename, 'w', encoding=character_encoding) as file:
    file.write(unicode_text)

Возможно, было бы более удобно, если вам нужно постепенно писать текст (вам не нужно многократно называть unicode_text.encode(character_encoding)). В отличие от модуля codecs модуль io имеет правильную универсальную поддержку новых строк.

48
ответ дан jfs 22 August 2018 в 15:37
поделиться
  • 1
    Человек, я потратил так много времени, чтобы найти это! Спасибо! – Georgy Gobozov 22 February 2018 в 02:02
  • 2
    Это тоже работает для Python 3 (очевидно, но все же стоит отметить). – Hippo 28 June 2018 в 08:36

Обработка строки Unicode стандартизована в Python 3.

  1. Char хранится в Unicode
  2. Вам нужно только открыть файл в utf-8
    out1 = "(嘉南大圳 ㄐㄧㄚ ㄋㄢˊ ㄉㄚˋ ㄗㄨㄣˋ )"
    fobj = open("t1.txt", "w", encoding="utf-8")
    fobj.write(out1)
    fobj.close()
    
8
ответ дан Rob 22 August 2018 в 15:37
поделиться
  • 1
    Но это не работает на Python 2, верно? (Я должен был сказать, что на этом коде Python 3 он выглядит настолько кратким и разумным) – Liwen Zhao 15 October 2017 в 19:35
  • 2
    он не должен работать на Python 2. Мы остаемся на Python 3. 3 намного лучше. – david m lee 16 October 2017 в 04:31

Эта ошибка возникает при попытке кодировать строку, отличную от юникода: она пытается ее декодировать, предполагая, что она находится в простой ASCII. Есть две возможности:

  1. Вы кодируете его в байтовую строку, но поскольку вы использовали codecs.open, метод write ожидает объект unicode. Поэтому вы кодируете его, и он пытается его снова декодировать. Попробуйте: f.write(all_html).
  2. all_html не является, по сути, объектом unicode. Когда вы делаете .encode(...), он сначала пытается его декодировать.
1
ответ дан Thomas K 22 August 2018 в 15:37
поделиться

Файл, открытый codecs.open, является файлом, который принимает данные unicode, кодирует его в iso-8859-1 и записывает в файл. Однако вы пытаетесь написать не unicode; вы берете unicode и кодируете его в iso-8859-1 самостоятельно . Это то, что делает метод unicode.encode, а результат кодирования строки юникода - это bytestring (тип str.)

Вы должны либо использовать обычный open(), либо самостоятельно закодировать юникод, либо (обычно лучшая идея), используйте codecs.open() и not сами кодировать данные.

18
ответ дан Thomas Wouters 22 August 2018 в 15:37
поделиться
Другие вопросы по тегам:

Похожие вопросы: