I'm coding a little app that asks a question using display dialog with default answer "", takes whatever the user input is (let's say die Universität), and sends it to a Python file. Python checks the spelling of the word, translates it, spits out a display dialog with the English translation.
The problem I'm having is that Applescript is not giving Python a nice encoding. Here's my code in Applescript:
set phrase to the text returned of (display dialog "Enter German Phrase" default answer "")
set command to "python /Users/Eli/Documents/Alias\\ Scripts/gm_en.py " & phrase
do shell script command
I get the input into Python. It's breaking everything, so I'm using chardet to figure out what the encoding is. It's giving me this: {'confidence': 0.7696762680042672, 'encoding': 'ISO-8859-2'}
Not only is this pretty innacurrate, it's an encoding I can find very little about online. Trying to convert with decode('iso-8859-2') gives very strange symbols.
Any ideas?
Related
I have a python 2.7.10 script that takes a user's input and inserts it into the name and body parameter of the make new note AppleScript.
The problem is that any escape or special characters get interpreted by AppleScript. I want all strings to be treated as raw and to ignore all escape characters and things like :\//tft// or c:\test\test.txt without giving me a Expected “"” but found unknown token. error or ignoring the t character after the \
The line of python looks like this:
cmd = "osascript -e 'tell application \"Notes\" \n tell account \"iCloud\" \n make new note at folder \"Notes\" with properties {name:\"%s\", body:\"%s\"} \n end tell \n end tell'" % (header, body)
... where header and body are the user supplied strings.
But for manual testing I use the Script Editor to quickly reproduce the error.
tell application "Notes"
tell account "iCloud"
make new note at folder "Notes" with properties {name:"myname", body:"c:\test\test.txt"}
end tell
end tell
This particular note ends up looking like this:
I know that I can use \\ instead of \ but I don't want users to have to sanitize all their input as they could be copy pasting from a large body of text. Think of a log file or paste-bin style body of text.
Is there a way to programmatically sanitize the user's input?
NOTE:
This is NOT a duplicate of this question because I've tried replacing the string variable header and body with eval(header) and eval(body) but that didn't work. I also tried .decode('string_escape') to no avail. Finally, I tried this with no luck either:
d = header.escape('\w[0-9]')
header = d.decode('string_escape')
I think this has to do with AppleScript's ability to accept this string and not just Python's ability to sanitize it using the above functions.
UPDATE
I am capturing user input using a dialog box with code like this:
cmd = "osascript -e \'set theString to text returned of (display dialog \"Please Enter The Note To Add To Your iCloud Notes \" with icon file \"%s\" default answer \"\n\n\n\" buttons {\"OK\",\"Cancel\"} default button 1) \'" % (appicon_abs_path_apple)
note = run_script(cmd)
In the demo.py gist below there is a custom sanitize function which is utilized to escape any backslash (\) or double quote (") character(s) that the user may enter into the dialog box. It's necessary to escape these characters this way in your .py file prior to subsequently passing them to osascript.
demo.py
#!/usr/bin/env python
from subprocess import Popen, PIPE
def sanitize(str):
return str.replace("\\", "\\\\") \
.replace("\"", "\\\"")
def run_script(script):
p = Popen(['osascript', '-'], stdin=PIPE, stdout=PIPE, stderr=PIPE)
stdout, stderr = p.communicate(script)
return stdout
appicon_abs_path_apple = "Applications:Stickies.app:Contents:Resources:Stickies.icns"
input_dialog = """
tell application "Finder"
activate
set mssg to "Please Enter The Note To Add To Your iCloud Notes"
set theString to text returned of (display dialog mssg with icon file "%s" \
default answer "\n\n\n" buttons {"OK", "Cancel"} default button 1)
end tell
""" % (appicon_abs_path_apple)
# Notice in the following line we `sanitize` the text characters returned
# from the input dialog before assigning it to the `note` variable.
note = sanitize(run_script(input_dialog))
# -------------------------------
# Let's test that any special characters have been preserved
show_input = """
tell application "Finder"
activate
display dialog "%s"
end tell
""" % (note)
run_script(show_input)
Notes:
The show_input and run_script(show_input) parts at the end of demo.py are for test purposes only. This should be replaced with the AppleScript code necessary to make a new note. For instance:
# ...
# ...
note = sanitize(run_script(input_dialog))
# header = sanitize(header)
make_note = """
tell application "Notes"
tell account "iCloud"
make new note at folder "Notes" with properties {name:"%s", body:"%s"}
end tell
end tell
""" % (header, note)
run_script(make_note)
You'll probably also want to consider passing the text string assigned to the header variable through the sanitize function (as per the line currently commented out in snippet above), however I'm unsure from your question where that data comes from. If it's user generated then definitely sanitize it.
Also note how in the aforementioned gist we wrap the Applescript code in triple double quotes (""") - this helps to make the code more readable and avoids the need for additional escaping and \n character(s), unlike the following:
make_note = "osascript -e 'tell application \"Notes\" \n tell account \"iCloud\" \n make new note at folder \"Notes\" with properties {name:\"%s\", body:\"%s\"} \n end tell \n end tell'" % (header, body)
Demo:
To test the demo.py gist above you'll need to:
Ensure the file is executable by running something like the following chmod command and changing the file path as necessary.
chmod +x /some/path/to/demo.py
Also, you'll probably want to change the HFS path path (i.e. a colon separated path) which is assigned to the appicon_abs_path_apple variable - currently it utilizes the icon for the Stickies application.
Input:
The following arbitrary text string containing special characters was entered into the dialog:
:\//tft//
c:\test\test.txt
c:\\quux\\foo.md
'¡"€#¢∞§¶•ª⁄™‹›fifl‡°·
Screenshot (above) showing the input text includes many special characters.
Output:
Screenshot (above) showing that the special characters in the input text have been preserved in the subsequent dialog.
It seems to me this is a python question more than an AppleScript question. I mean, if you were asking for the body text through AppleScript, using, say:
display dialog "Enter Note" default answer ""
AppleScript would automatically escape any problem characters (i.e., if they entered c:\test\test.txt, the result of that display dialog command would be c:\\test\\test.txt). It seems to me you are getting the text from some other source and using python to send it on through AppleScript. That means you have to escape it all in python before sending it to osascript.
Escaping is fairly easy, analytically: replace every backslash with a double-backslash. In python I think that would be something like:
body.replace('\','\\')
Depending on the text you're receiving you might need to tweak it some. For instance, if you have bald double-quotes you'll need to escape them:
body.replace('"','\"')
and if you have plain-text tabs, carriage returns, or line feeds (\t, \r, \n) built into the text you may have to find some way of avoiding escaping those (you may have to dig into regular expressions for that). But the idea is to put the AppleScript escapes in first, in python, and then call your osacript command.
EDIT:
Now that I know that you're getting the user text from display dialog, I'm going to suggest you cut out the python middle-man and handle the whole thing in AppleScript. The script you want is this:
set txt to text returned of (display dialog "Please Enter The Note To Add To Your iCloud Notes" default answer "\n\n\n")
tell application "Notes"
tell account "iCloud"
make new note at folder "Notes" with properties {name:"myname", body:txt}
end tell
end tell
You can either save this as a script file and call it from osascript — osascript scriptName.scpt — or you can enter it directly into osascript using sequential -e options:
osascript -e 'set txt to text returned of (display dialog "Please Enter The Note To Add To Your iCloud Notes" default answer "\n\n\n")' -e 'tell application "Notes"' -e 'tell account "iCloud"' -e 'make new note at folder "Notes" with properties {name:"myname", body:txt}' -e 'end tell' -e 'end tell'
if you need to pass arguments into the script (like, say, a variable for the username or a path to an icon) you'll need to use an explicit run handler. See 'man osascript,' or ask and I'll show you how.
Here’s how to parameterize an AppleScript run via osascript:
#!/usr/bin/env python
import subprocess
header ='my name'
body = 'some text'
subprocess.call(['osascript',
'-e', 'on run {theHeader, theBody}',
'-e', ' tell application "Notes"',
'-e', ' tell account "iCloud"',
'-e', ' make new note at folder "Notes" with properties {name:theHeader, body:theBody}',
'-e', ' end tell',
'-e', ' end tell',
'-e', 'end run', '--', header, body])
For passing more complex data, consider py-applescript or PyObjC + AppleScript-ObjC.
I can not write on a standard Georgian language in the Text widget. instead of letters writes question marks .
when no tkinter, ie, when writing code, Georgian font recognized without problems. Plus, if I copy the word written in Georgian and inserted in the text widget, it is displayed correctly.
this is elementary code that displays the text box on the screen, where I want to write a word in Georgian.
import tkinter
root = tkinter.Tk()
txt = tkinter.Text(root)
txt.pack()
root.mainloop()
the first image shows how the word is displayed when the selected Georgian language.
the second shot, when I write in the code in Georgian, and define in advance the value of text field. in this case, the text in the field is displayed normally.
Okay, so here is how I achieved it:
First, make sure you have a Georgian font installed in your computer; if there is no any, then go download one (I downloaded mine from here);
Now, go to your tkinter program, and add your font to your Text widget:
txt = tkinter.Text(root, font=("AcadNusx", 16))
NOTE 1: My font name that supports Georgian is AcadNusx, but yours can be different;
NOTE 2: If you have not imported Font, then import it at the beginning of your program;
NOTE 3: Do not change your computer's font to Georgian, because you have already changed it inside the program, so make sure it is set to English.
The best answer I can determine so far is that there is something about Georgian and keyboard entry that tk does not like, at least not on Windows.
Character 'translation' is usually called 'transliteration'.
Tk text uses the Basic Multilingual Plane (the BMP, the first 2**16 codepoints) of Unicode. This includes the Georgian alphabet. The second image shows that the default Text widget font on your system is quite capable of displaying Georgian characters once the characters are in the widget. So a new display font does not seem to be the solution to your problem.
('ქართული ენა' is visible on Firefox because FF is unicode based and can display most if not all of the BMP.)
It looks like the problem is getting the proper codes to tk without going through your editor. What OS and editor are your using. How did you enter the mixed-alphabet line similar to
txt.insert('1.0', 'ქართული ენა') # ? (I cannot copy the image string.)
How are you running the Python code? If you cut the question marks from the first image and insert into
for c in '<insert here>': print(ord(c))
what do you see?
You need a 'Georgian keyboard entry' or 'input method' program (Google shows several) for your OS that will let you switch back and forth between sending ascii and Geargian codes to any program reading the keyboard.
Windows now comes with this, with languages activated on a case-by-case basis. I already had Spanish entry, and with it I can enter á and ñ both here and into IDLE and a fresh Text box. However, when I add Georgian, I can type (randomly ;-) ჰჯჰფგეუგსკფ here (in FireFox, also MS Edge) but only get ?????? in tk Text boxes. And these are actual ascii question marks, ord('?') = 63, rather that replacements for codes that cannot be represented. Japanese also works with tk-Text based IDLE. So the problem with Georgian is not generic to all non-latin alphabets.
I have to use Turkish characters, when I write "chcp" in cmd, I see 857.
So I tried to start my programs with:
# -*- coding: cp857 -*-
but nothing changed.Still I cant see Turkish characters like "ş,İ,Ş,Ğ" etc.
So I tried to start my programs with:
# -*- coding: cp1254 -*-
with this,I can see the Turkish characters,BUT when my program needs data from user, I cant see the Turkish characters again so my program is nothing. its like:
name=raw_input("Please enter your name: ")
print name
--------
Please enter your name: Ayşe
A*/8e
so,if I have to find user's name in a list in my program, I cant find "Ayşe" because program doesnt understand Turkish characters, but it shows Turkish characters at the beginning of program.The problem appears when I need data from user..
It doesnt make any sense, I really want to know why and how can I fix it.I tried tons of methods,none of them works..
Have a read of How to read Unicode input and compare Unicode strings in Python?, it should help you understand why raw_input isn't reading the name as you expect.
type chcp 65001 in console
right click the cmd window and change fonts to Lucida console
This is a duplicate of Unicode characters in Windows command line - how?
Also, you should really avoid users writing to console, it creates unnecessary complication to both you and the user
This question already has answers here:
Syntax error on print with Python 3 [duplicate]
(3 answers)
Closed 9 years ago.
Note: This was not answered by the question that was marked as the original. This is more than just a Python v2 vs v3 problem, which I explain in the comments below.
Original post:
I am trying to learn Python at work, so I am currently using Portable Python 3.2.1.1 (which will henceforth be referred to as PP). (I mention this because this problem doesn't happen at home when I use my Mac and regular Python.)
I am working through exercise 16 of Learning Python the Hard Way (http://learnpythonthehardway.org/book/ex16.html). I've heard this isn't the best learning tool, but I am a complete programming n00b and I'm a hands-on learner. If you have any better suggestions, I'm open!
The first few lines of the exercise read:
from sys import argv
script, filename = argv
print "We're going to erase %r." % filename
print "If you don't want that, hit CTRL-C (^C)."
My script is titled Ex16.py and the file I am using is Python.txt, and both of these are in the same folder as the PP .exes. I don't think that's necessary, but hoped maybe it would fix the problem... negative. When I press "Run" in PP, it doesn't work because argv requires you provide an argument when you start the script: python Ex16.py Python.txt
When I launch Python.exe (which, in PP is Portable-Python.exe), I get the standard Python prompt, >>>, but whatever I enter I get the same error message:
File "<stdin>", line 1
with whatever I've just tried repeated back to me with the marker to
indicate where the problem is. (has not been helpful so far)
SyntaxError: invalid syntax
I have tried typing the following at the >>> prompt:
python Ex16.py Python.txt,,
Ex16.py Python.txt,,
"%PATH&\Ex16.py" "%PATH%\Python.txt" (with the actual filepaths),,
print 'hello world'
I just keep getting the same invalid syntax error over and over. Even a basic print command returned an invalid syntax error. The only one that triggered a different error was the one where I tried whole filepaths. That one returned:
File "<stdin>", line 1
SyntaxError: (unicode error) 'unicodeescape' codec can't decode bytes in
position 2-3: truncated \UXXXXXXXX escape
Yes, I have Googled the crap outta both errors. I read that sometimes the problem is not doubling the backspaces, so I tried that, too, putting two \ where just one had been before in both filepaths. I even tried putting — # -*- coding: utf-8 -*- at the beginning of the script thinking maybe there was some unicode error. That, with the full filepaths, resulted in the same unicode error mentioned earlier.
Yes, I have checked that my code is matching that in the exercise.
Yes, this works at home on non-PP.
All this leads me to believe that the problem is probably in the way I'm trying to run the scripts in PP (but why won't print work?), but I haven't a clue what I'm doing wrong.
Thanks!
print is a function in Python 3:
print('my string with content and the like')
It is no longer supported as being a 'statement'. You might want to check out a list of things that changed from python2.x to python3.x (there's a number of incompatibilities). Also, you might be better off finding a tutorial using Python3.
You have to type:
Portable-Python.exe Ex16.py Python.txt
at your command prompt. To get a command prompt, press WindowsKey-R, then type "cmd" and press enter. You should now be looking at something like c:\>. Navigate to your portable python installation by using the cd command.
I want someone to type words in the console, and autocomplete from a list when they hit "tab" key. However, raw_input won't return a string until someone hits [Enter].
How do I read characters into a variable until the user hits [Enter]?
*Note: I don't want to use import readline for autocompletion because of OS issues.
There is an official FAQ entry on this question, for Unix: http://www.python.org/doc/faq/library/#how-do-i-get-a-single-keypress-at-a-time
Edit (copied from Donal Fellows' comment below): "The problem is that the terminal is in “cooked” mode by default (allowing simple line editing) and that to get the keys as they're typed, it has to be placed in “raw” mode." (Thanks!)
On *nix use select on sys.stdin to wait for a character, then .read() it in. On Windows use msvcrt.kbhit() and msvcrt.getch().