use=input('what do you wanna do \n1.press w to create a new file\n2.press r to read a file:\n')
if use=='r':
read()
elif use=='w':
write()
else :
print('OOPS! you enter a wrong input\n')
user()
when i run this code using IDLE it runs properly but when i created a exe of this python file using cx_freeze then the if and elif conditions are not working for 'r' and 'w' respectively. for any input it always goes to the else statement.
I am using python 3.2 and cx_freeze 3.2
Just for a quick test, I did this:
use = input("test input here: ")
for i in use:
print(ord(i))
The result, if you type in "hello", is the ascii character codes for hello, plus "13". This is \r, the return character, which is being added to your string. This doesn't happen under Linux and is the result of the fact on Windows a newline is \r\n as opposed to just \n.
The workaround for you would be to do something like:
use = input("test input: ").strip("\r")
strip() is a string object method that'll remove characters from the end and beginnings of strings.
Notes:
The use of ord() in the above example is probably not best practise - see Unicode.
If you ever write GUIs and use cx_freeze, don't use print() or input() - on Windows the standard input/output handles don't exist for GUI apps at all. That tripped me up for a while with cx_freeze + gui code. Just a note for when you get there.
Related
I am on windows 10 and I prefer not to install a new module (standard library solutions are accepted). I want the text that the user enters to start at the end of the third line.
My code:
print(" Enter password to unlock the Safe .\n\n password : \n\n\t2 attempts remaining .")
# code to move the cursor to the end of " password : " goes here
x = input()
output:
wanted output:
Also ANSI escape sequences don't seem to work without colorama(which unfortunately is an external module).
On Windows 10 you can use ANSI escape sequences as found in Console Virtual Terminal Sequences.
Before using them you need subprocess.run('', shell=True) (prior to Python 3.5, use subprocess.call). These sequences make possible what you are looking for.
Caution: Also original Microsoft, the documentation of Erase in Display and Erase in Line is partly faulty. The parameters 1 and 2 are reversed.
This should work (although, actually entering the password seems to destroy the layout):
import subprocess
subprocess.run('', shell=True)
print(' enter password : \0337', end='')
print('\n\n\t2 attempts remaining .\0338', end='')
x = input()
With Python 3 use;
print("...", end="")
I was trying to write a Python 2.7 script that processes a Unix directory input and use the input as a parameter to start another program.
However, I run into a problem that python's str() function doesn't like slashes in the input. When I am trying to str() a input with slashes, just like:
inputData = str(input('Put directory here:')) // OS is Mac OS X
> Put directory here: /User/username/abc.file
...
SyntaxError: invalid syntax
I think this is due to str() cannot naturally process a string with slashes, because if I manually add quotes on each site during the input (keyboard input "/User/username/abc.file"), this error will not be triggered.
As this script needs to process user input, I hope it can add quotes automatically. I tried the following walk-around:
inputDataRaw = input('Put directory here:')
if (not inputDataRaw.startswith('"')) and (not inputDataRaw.startswith("'")):
inputDataRaw = '"' + inputDataRaw
if (not inputDataRaw.endswith("'")) and (not inputDataRaw.endswith('"')):
inputDataRaw = inputDataRaw + '"'
inputData = str(inputDataRaw)
But apparently the input value cannot be stored in inputDataRaw without str()ing it, and the first line directly triggered the same error. It looks like all functions that escape a slash in python can't work without forming a string first.
Would anyone please point out the correct way to walk-around this problem? Thanks.
input attempts to eval the given input. That is, it's expecting something that would be a valid Python literal - including quotes for a string value. Use raw_input instead - that always returns the string the user entered, leaving conversions to your code.
From the docs:
Equivalent to eval(raw_input(prompt)).
This function does not catch user errors. If the input is not syntactically valid, a SyntaxError will be raised. Other exceptions may be raised if there is an error during evaluation.
If the readline module was loaded, then input() will use it to provide elaborate line editing and history features.
Consider using the raw_input() function for general input from users.
The problem is that you are not using python comments ;-)
Change:
inputData = str(input('Put directory here:')) // OS is Mac OS X
to:
inputData = str(input('Put directory here:')) # OS is Mac OS X
So what I'm trying to do is to join something in the form of
os.path.join('C:\path\to\folder', 'filename').
**edit :
Actual code is :
filename = 'creepy_%s.pcl' % identifier
file = open(os.path.join(self.cache_dir, filename), 'w')
where self.cache_dir is read from a file using configobj (returns string) and in the particular case is '\Documents and Settings\Administrator\creepy\cache'
The first part is returned from a configuration file, using configobj. The second is a concatenation of 2 strings like: 'file%s' % name
When I run the application through the console in windows using the python interpreter installed, I get the expected result which is
C:\\path\\to\\folder\\filename
When I bundle the same application and the python interpreter (same version, 2.6) in an executable in windows and run the app the result is instead
C:\\path\\to\\folderfilename
Any clues as to what might be the problem, or what would cause such inconsistencies in the output ?
Your code is malformed. You need to double those backslashes or use a raw string.
os.path.join('C:\\path\\to\\folder', 'filename').
I don't know why it works in one interpreter and not the other but your code will not be interpreted properly as is. The weird thing is i'd have expected a different output, ie: C:pathtofolder\filename.
It is surprising behavior. There is no reason it should behave in such a way.
Just be be cautious, you can change the line to the following.
os.path.join(r'C:\path\to\folder\', 'filename').
Note the r'' raw string and the final \
Three things you can do:
Use double-slashes in your original string, 'C:\\path\\to\\folder'
Use a raw string, r'C:\path\to\folder'
Use forward-slashes, 'C:/path/to/folder'
I figure it out yesterday. As usual when things seem really strange, the explanation is very simple and most of the times involve you being stupid.
To cut a long story short there were leftovers from some previous installations in dist-packages. The bundled interpreter loaded the module from there , but when i ran the python script from the terminal , the module (newer version) in the current dir was loaded. Hence the "unpredictable" results.
I wrote my module in Python 3.1.2, but now I have to validate it for 2.6.4.
I'm not going to post all my code since it may cause confusion.
Brief explanation:
I'm writing a XML parser (my first interaction with XML) that creates objects from the XML file. There are a lot of objects, so I have a 'unit test' that manually scans the XML and tries to find a matching object. It will print out anything that doesn't have a match.
I open the XML file and use a simple 'for' loop to read line-by-line through the file. If I match a regular expression for an 'application' (XML has different 'application' nodes), then I add it to my dictionary, d, as the key. I perform a lxml.etree.xpath() query on the title and store it as the value.
After I go through the whole thing, I iterate through my dictionary, d, and try to match the key to my value (I have to use the get() method from my 'application' class). Any time a mismatch is found, I print the key and title.
Python 3.1.2 has all matching items in the dictionary, so nothing is printed. In 2.6.4, every single value is printed (~600) in all. I can't figure out why my string comparisons aren't working.
Without further ado, here's the relevant code:
for i in d:
if i[1:-2] != d[i].get('id'):
print('X%sX Y%sY' % (i[1:-3], d[i].get('id')))
I slice the strings because the strings are different. Where the key would be "9626-2008olympics_Prod-SH"\n the value would be 9626-2008olympics_Prod-SH, so I have to cut the quotes and newline. I also added the Xs and Ys to the print statements to make sure that there wasn't any kind of whitespace issues.
Here is an example line of output:
X9626-2008olympics_Prod-SHX Y9626-2008olympics_Prod-SHY
Remember to ignore the Xs and Ys. Those strings are identical. I don't understand why Python2 can't match them.
Edit:
So the problem seems to be the way that I am slicing.
In Python3,
if i[1:-2] != d[i].get('id'):
this comparison works fine.
In Python2,
if i[1:-3] != d[i].get('id'):
I have to change the offset by one.
Why would strings need different offsets? The only possible thing that I can think of is that Python2 treats a newline as two characters (i.e. '\' + 'n').
Edit 2:
Updated with requested repr() information.
I added a small amount of code to produce the repr() info from the "2008olympics" exmpale above. I have not done any slicing. It actually looks like it might not be a unicode issue. There is now a "\r" character.
Python2:
'"9626-2008olympics_Prod-SH"\r\n'
'9626-2008olympics_Prod-SH'
Python3:
'"9626-2008olympics_Prod-SH"\n'
'9626-2008olympics_Prod-SH'
Looks like this file was created/modified on Windows. Is there a way in Python2 to automatically suppress '\r'?
You are printing i[1:-3] but comparing i[1:-2] in the loop.
Very Important Question
Why are you writing code to parse XML when lxml will do all that for you? The point of unit tests is to test your code, not to ensure that the libraries you are using work!
Russell Borogrove is right.
Python 3 defaults to unicode, and the newline character is correctly interpreted as one character. That's why my offset of [1:-2] worked in 3 because I needed to eliminate three characters: ", ", and \n.
In Python 2, the newline is being interpreted as two characters, meaning I have to eliminate four characters and use [1:-3].
I just added a manual check for the Python major version.
Here is the fixed code:
for i in d:
# The keys in D contain quotes and a newline which need
# to be removed. In v3, newline = 1 char and in v2,
# newline = 2 char.
if sys.version_info[0] < 3:
if i[1:-3] != d[i].get('id'):
print('%s %s' % (i[1:-3], d[i].get('id')))
else:
if i[1:-2] != d[i].get('id'):
print('%s %s' % (i[1:-2], d[i].get('id')))
Thanks for the responses everyone! I appreciate your help.
repr() and %r format are your friends ... they show you (for basic types like str/unicode/bytes) exactly what you've got, including type.
Instead of
print('X%sX Y%sY' % (i[1:-3], d[i].get('id')))
do
print('%r %r' % (i, d[i].get('id')))
Note leaving off the [1:-3] so that you can see what is in i before you slice it.
Update after comment "You are perfectly right about comparing the wrong slice. However, once I change it, python2.6 works, but python3 has the problem now (i.e. it doesn't match any objects)":
How are you opening the file (two answers please, for Python 2 and 3). Are you running on Windows? Have you tried getting the repr() as I suggested?
Update after actual input finally provided by OP:
If, as it appears, your input file was created on Windows (lines are separated by "\r\n"), you can read Windows and *x text files portably by using the "universal newlines" option ... open('datafile.txt', 'rU') on Python2 -- read this. Universal newlines mode is the default in Python3. Note that the Python3 docs say that you can use 'rU' also in Python3; this would save you having to test which Python version you are using.
I don't understand what you're doing exactly, but would you try using strip() instead of slicing and see whether it helps?
for i in d:
stripped = i.strip()
if stripped != d[i].get('id'):
print('X%sX Y%sY' % (stripped, d[i].get('id')))
I have this code in Python
inputted = input("Enter in something: ")
print("Input is {0}, including the return".format(inputted))
that outputs
Enter in something: something
Input is something
, including the return
I am not sure what is happening; if I use variables that don't depend on user input, I do not get the newline after formatting with the variable. I suspect Python might be taking in the newline as input when I hit return.
How can I make it so that the input does not include any newlines so that I may compare it to other strings/characters? (e.g. something == 'a')
You are correct - a newline is included in inputted. To remove it, you can just call strip("\r\n") to remove the newline from the end:
print("Input is {0}, including the return".format(inputted.strip("\r\n")))
This won't cause any issues if inputted does not have a newline at the end, but will remove any that are there, so you can use this whether inputted is user input or not.
If you don't want any newlines in the text at all, you can use inputted.replace("\r\n", "") to remove all newlines.
Your problem is actually Eclipse. Assuming that you use PyDev, I was able to reproduce the problem. When entering something in the Eclipse console, the problem occurs as described in your question. But when directly executing the very same script with the Python 3.1.1 interpreter, inputted does not include a newline character.
I investigated the Python source code and found out input() uses GNU readline if stdin is interactive (i.e. a TTY or prompt, however you want to call it), but falls back to the .readline() method of the stdin object if necessary. Then, if the result of readline ends with \n, that character is removed. Note: No CR-LF or LF-CR handling here (in the fallback case)!
So I wrote this little script to see what actually happens:
import sys
from io import StringIO
for stdin in [sys.stdin, StringIO("test\r\ntest\r\n")]:
sys.stdin = stdin
print("readline returns this: " + repr(sys.stdin.readline()))
inputted = input("Enter in something: ")
print("inputted: " + repr(inputted))
print("inputted is printed like this: --> {0} <--".format(inputted))
It first executes the code with the normal stdin (console or Eclipse console) and then with a prepared stdin containing the text test\r\ntest\r\n.
Try and run the script in Eclipse - you must enter a string twice. The conclusion: Pressing Enter in the Eclipse console will produce CR-LF ("\r\n"). Printing "\r" in the Eclipse console will jump to the next line.
On the other side, running it in the Windows console will produce the expected output: input() returns a string without a newline at the end because (I guess) GNU readline is used. With the prepared stdin StringIO("test\r\n"), the input() result is "test\r" as in Eclipse (although not printed as newline).
Hope this all makes sense... but what I still don't know is if that is expected behavior of Eclipse.
If you only want to stript the last line endings, you could use rstrip.
inputted.rstrip ("\r\n")
inputted = inputted.strip()
Edit: As noted, this will kill all whitespace at the start and end. A way to get rid of only the trailing newline is:
import re
inputted = re.sub("[\n\r]+$", "", inputted)