1

I am trying to write data to a file in a non-roman script using python tkinter. I want to write data to a file in Hindi language which follows the Devanagari Script. While, it is working perfectly alright when I write some data in English, while writing to the file in Hindi language is throwing some errors. How do I resolve this issue?

I tried adding (encoding='utf-8') in filedialog command. Doing this, it gives the following error:

_tkinter.TclError: bad option "-encoding": must be -confirmoverwrite, -defaultextension, -filetypes, -initialdir, -initialfile, -parent, -title, or -typevariable

This error shows up the moment I click the button.Maybe (encoding='utf-8') is not an attribute of filedialog. Following is the relevant part of the code:

def save_file_hindi(event=""):
    data = filedialog.asksaveasfile(mode="w", defaultextension=".html")
    if data is None:
        return

    data.write("एक" + "<br>\n"+ "दो" + "<br>\n")
    data.close()

Expected Result: In the saved HTML file, it should display:

एक

दो

Actual Result: UnicodeEncodeError: 'charmap' codec can't encode characters in position 19-26: character maps to undefined

Pratyush Karna
  • 179
  • 1
  • 2
  • 10
  • you might want to take a look at this link: https://stackoverflow.com/questions/34645856/how-to-write-foreign-encoded-characters-to-a-text-file – Hass786123 Apr 01 '19 at 16:37
  • I have tried using encoding='utf=8', but it didn't work and showed up a different error altogether like I mentioned. Anyway, I will try some other methods and check if it works or not. – Pratyush Karna Apr 01 '19 at 16:41

4 Answers4

1

Tried this code and it worked just fine with Python 3.6.5 under Windows 10:

text = """<html><head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
</head><body>
<p>एक  दो</p>
</body></html>"""

with open('test.html', 'w', encoding='utf8') as file:
    file.write(text)

What is your environment? Have you tried to open the file in different editors and/or browsers?

figbeam
  • 7,001
  • 2
  • 12
  • 18
1

For python : in json.dump() add ensure_ascii=False which will allow you to save data in Hindi as it is without converting non-ASCII char be escaped.

amritkv88
  • 17
  • 3
0

According to the File Dialogs documentation for asksaveasfilename, there is no encding option available. But you can open the file in write mode, specify the encoding as 'utf-8', and write to it later.

import tkinter as tk
from tkinter import filedialog

def Test():        
    root = tk.Tk()

    myFile = filedialog.asksaveasfilename(defaultextension='.html')

    if not myFile:
        return        

    with open(myFile, 'w', encoding='utf-8') as f:
        f.write("एक" + "<br>\n"+ "दो" + "<br>\n")   

    root.mainloop()


Test()
amanb
  • 5,276
  • 3
  • 19
  • 38
  • You should actually use `asksaveasfilename` to avoid opening the file twice. – Davis Herring Apr 01 '19 at 21:50
  • Though it works this way too, but I agree that behind the scenes the file is opened twice. Editing the answer, thanks for pointing out. – amanb Apr 01 '19 at 21:54
0

I found a very feasible solution to the problem I was facing earlier. So, I am answering my own question as it might turn out handy for anyone who runs into an error similar to mine. The solution shall work for writing to a file in any language that is in a non-roman script (Hindi,Urdu, Chinese, Russian, Arabic etc). The programming environment I am working in is python 3.6.

The only rectifications to the code are-

  1. Change mode='w' to mode='wb', so that the data to be written in file is read in bytes since for any form of encoding, the interpreter must scan the data in bytes.
  2. In the (.write) command line, add encoding in the form of .encode('utf-8'). As, I mentioned in my problem, encode='utf-8' is not an 'attribute' of (filedialog.asksaveasfile). However, it is actually a 'method' and is it be to formulated that way only. So, the new rectified code is-

     def save_file_hindi(event=""):
     data = filedialog.asksaveasfile(mode="wb", defaultextension=".html")
     if data is None:
         return
    
     data.write(("एक" + "<br>\n"+ "दो" + "<br>\n").encode('utf-8'))
     data.close()
    
Pratyush Karna
  • 179
  • 1
  • 2
  • 10