I've met a strange problem while doing the 16th exercice of Learn Python the Hard Way (2nd edition, LPTHW).
I have first typed the code, the copied it, and when I execute the script on my console (with python ex16.py test.txt), the same message appears:
File "ex16.py", line 19, in <module>
line1 = input("line 1: ")
TypeError: 'str' object is not callable
The code is:
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).")
print("If you do want that, hit RETURN.")
input = ("?")
print("Opening the file...")
target = open(filename, 'w')
print("Truncating the file. Goodbye!")
target.truncate()
print("Now I'm going to ask you for three lines.")
line1 = input("line 1: ")
line2 = input("line 2: ")
line3 = input("line 3: ")
print("I'm going to write these to the file.")
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
print("And finally, we close it.")
target.close()
Is this caused by the fact that LPTHW is made for Python 2.7 and I use Python 3.3?
You shadowed the builtin input function right here:
input = ("?")
The equal sign assigns to a variable named input, which shadows the built-in input() function. Remove the equal sign and your code will work:
input("?")
input = ("?")
comment out the above and retry the script.
Related
I'm not exactly sure how to word this to be honest, but here's a simplified version of my current code.
for idx in range(0,11):
print('Failed:',idx)
This outputs:
Failed: 0
Failed: 1
Failed: 2
Failed: 3
Failed: 4
Failed: 5
Failed: 6
Failed: 7
Failed: 8
Failed: 9
Failed: 10
I'm trying to replace the original int with the next int in the range instead of spamming my terminal with a new line for every int in the range.
How could I update "Failed: 1" to "Failed: 2" without creating a new line for "Failed: 2"?
Sorry if this is poorly worded, if you're willing to help me but like me to elaborate further please say so and I will try my best.
What you probably want to do is change 'Failed: 1' to 'Failed: 2', not have 'Failed: 1 Failed: 2' on the same line or new lines.
The ASCII backslash b (backspace) helps erase characters on the same line. You'd want to move the cursor back to where the last number was and replace it.
Here's a simple program that moves back on the same line and replaces the counter.
import time
import sys
print(0, end="")
prev = 0
for i in range(20):
print(("\b" * (len(str(prev)) + 1)), i, end="")
sys.stdout.flush()
prev = i
time.sleep(1)
And to complete your example:
import time
import sys
last_idx = None
prefix = ''
print("Failed: ", end="")
for idx in range(0,11):
if last_idx is not None:
prefix = '\b' * len(str(last_idx))
print(prefix + str(idx), end='')
# python buffers output so you want to flush it everytime.
sys.stdout.flush()
last_idx = idx
# I've added a time.sleep here so you can see it happen rather than zoom past you
time.sleep(1)
Alternatively, instead of just backspacing few characters, you can go back to the beginning of the line with "carriage return" (\r instead of \b).
Try this :
import sys
import time
for i in range(10):
sys.stdout.write("\rFailed: {}".format(i))
sys.stdout.flush()
time.sleep(0.5)
There is a second parameter that the function print takes to to specify what should print do at the end of line
print("Text here", end="")
whoops let's try again...
Your only option is to clear the whole console between prints. there are two ways of going about this.
option 1: You could try and use ANSI escape sequence but might be a little flakey
print(chr(27)+'[2j')
print('\033c')
print('\x1bc')
Option 2: use the os module
from os import system, name
# Only on Unix
system('cls')
# Only on windows
system('clear')
I am trying to pull a string of input names that get saved to a text file. I need to pull them by capital letter which is input. I.E. the saved text file contains names DanielDanClark, and I need to pull the names that begin with D. I am stuck at this part
for i in range(num):
print("Name",i+1," >> Enter the name:")
n=input("")
names+=n
file=open("names.txt","w")
file.write(names)
lookUp=input("Did you want to look up any names?(Y/N)")
x= ord(lookUp)
if x == 110 or x == 78:
quit()
else:
letter=input("Enter the first letter of the names you want to look up in uppercase:")
file=open("names.txt","r")
fileNames=[]
file.list()
for letter in file:
fileNames.index(letter)
fileNames.close()
I know that the last 4 lines are probably way wrong. It is what I tried in my last failed attempt
Lets break down your code block by block
num = 5
names = ""
for i in range(num)
print("Name",i+1," >> Enter the name:")
n=input("")
names+=n
I took the liberty of giving num a value of 5, and names a value of "", just so the code will run. This block has no problems. And will create a string called names with all the input taken. You might consider putting a delimiter in, which makes it more easier to read back your data. A suggestion would be to use \n which is a line break, so when you get to writing the file, you actually have one name on each line, example:
num = 5
names = ""
for i in range(num)
print("Name",i+1," >> Enter the name:")
n = input()
names += n + "\n"
Now you are going to write the file:
file=open("names.txt","w")
file.write(names)
In this block you forget to close the file, and a better way is to fully specify the pathname of the file, example:
file = open(r"c:\somedir\somesubdir\names.txt","w")
file.write(names)
file.close()
or even better using with:
with open(r"c:\somedir\somesubdir\names.txt","w") as openfile:
openfile.write(names)
The following block you are asking if the user want to lookup a name, and then exit:
lookUp=input("Did you want to look up any names?(Y/N)")
x= ord(lookUp)
if x == 110 or x == 78:
quit()
First thing is that you are using quit() which should not be used in production code, see answers here you really should use sys.exit() which means you need to import the sys module. You then proceed to get the numeric value of the answer being either N or n and you check this in a if statement. You do not have to do ord() you can use a string comparisson directly in your if statement. Example:
lookup = input("Did you want to look up any names?(Y/N)")
if lookup.lower() == "n":
sys.exit()
Then you proceed to lookup the requested data, in the else: block of previous if statement:
else:
letter=input("Enter the first letter of the names you want to look up in uppercase:")
file=open("names.txt","r")
fileNames=[]
file.list()
for letter in file:
fileNames.index(letter)
fileNames.close()
This is not really working properly either, so this is where the delimiter \n is coming in handy. When a text file is opened, you can use a for line in file block to enumerate through the file line by line, and with \n delimiter added in your first block, each line is a name. You also go wrong in the for letter in file block, it does not do what you think it should be doing. It actually returns each letter in the file, regardless of whay you type in the input earlier. Here is a working example:
letter = input("Enter the first letter of the names you want to look up in uppercase:")
result = []
with open(r"c:\somedir\somesubdir\names.txt", "r") as openfile:
for line in openfile: ## loop thru the file line by line
line = line.strip('\n') ## get rid of the delimiter
if line[0].lower() == letter.lower(): ## compare the first (zero) character of the line
result.append(line) ## append to result
print(result) ## do something with the result
Putting it all together:
import sys
num = 5
names = ""
for i in range(num)
print("Name",i+1," >> Enter the name:")
n = input("")
names += n + "\n"
with open(r"c:\somedir\somesubdir\names.txt","w") as openfile:
openfile.write(names)
lookup = input("Did you want to look up any names?(Y/N)")
if lookup.lower() == "n":
sys.exit()
letter = input("Enter the first letter of the names you want to look up in uppercase:")
result = []
with open(r"c:\somedir\somesubdir\names.txt", "r") as openfile:
for line in openfile:
line = line.strip('\n')
if line[0].lower() == letter.lower():
result.append(line)
print(result)
One caveat I like to point out, when you create the file, you open the file in w mode, which will create a new file every time, therefore overwriting the a previous file. If you like to append to a file, you need to open it in a mode, which will append to an existing file, or create a new file when the file does not exist.
im just curious while learning python3 and didn't found any good explanation on the web, neither here to my question.
reading about input() it says "reads from stdin" so i thought i might experiment and try to use it to read from pipe. and so it does! but only ONE LINE (till EOL). So the next question that came up was
how to read multiple lines from pipe (stdin) using input() ?
i found sys.stdin and used sys.stdin.isatty() to determine if stdin is bound to a tty or not, assuming that if not bound to tty the data is coming from pipe. and so i also found and used successfully sys.stdin.readlines() too to read multiple lines.
but just for my curiosity , is there a way to achieve the same by using the plain input() function ?? so far i didn't found something "to test" if stdin contains more lines without blocking my program.
sorry if all this makes no sense to you.
this is my experimenting code so far without input():
import sys
if sys.stdin.isatty(): # is this a keyboard?
print( "\n\nSorry! i only take input from pipe. "
"not from a keyboard or tty!\n"
"for example:\n$ echo 'hello world' | python3 stdin.py"
""
""
)
else:
print ( "reading from stdin via pipe : \n ")
for line in sys.stdin.readlines():
print(line, end="")
# ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ can these two lines be replaced with
# some construction using plain old input() ?
You can iterate over lines in stdin like any other iterable object:
for line in sys.stdin:
# do something
If you want to read the entire thing into one string, use:
s = sys.stdin.read()
Note that iterating over s would then return one character at a time.
Note that it won't read until there is an EOF terminating stdin.
if you just want to use input() to access lines of the stdin:
print(input()) #prints line 1
print(input()) #prints next line
but lets say you only wanted to access the second line:
input() #accesses the first line
print(input()) #prints second line
Lets say you wanted to take the second line and create an array:
stdin:
10
64630 11735 14216 99233 14470 4978 73429 38120 51135 67060
input()
values = list(map(int, input().split(' ')))
values will equal [64630, 11735, 14216, 99233, 14470, 4978, 73429, 38120, 51135, 67060]
So I am completely new to Python and can't figure out what's wrong with my code.
I need to write a program that asks for the name of the existing text file and then of the other one, that doesn't necessarily need to exist. The task of the program is to take content of the first file, convert it to upper-case letters and paste to the second file. Then it should return the number of symbols used in the file(s).
The code is:
file1 = input("The name of the first text file: ")
file2 = input("The name of the second file: ")
f = open(file1)
file1content = f.read()
f.close
f2 = open(file2, "w")
file2content = f2.write(file1content.upper())
f2.close
print("There is ", len(str(file2content)), "symbols in the second file.")
I created two text files to check whether Python performs the operations correctly. Turns out the length of the file(s) is incorrect as there were 18 symbols in my file(s) and Python showed there were 2.
Could you please help me with this one?
Issues I see with your code:
close is a method, so you need to use the () operator otherwise f.close does not do what your think.
It is usually preferred in any case to use the with form of opening a file -- then it is close automatically at the end.
the write method does not return anything, so file2content = f2.write(file1content.upper()) is None
There is no reason the read the entire file contents in; just loop over each line if it is a text file.
(Not tested) but I would write your program like this:
file1 = input("The name of the first text file: ")
file2 = input("The name of the second file: ")
chars=0
with open(file1) as f, open(file2, 'w') as f2:
for line in f:
f2.write(line.upper())
chars+=len(line)
print("There are ", chars, "symbols in the second file.")
input() does not do what you expect, use raw_input() instead.
Can you explain what is going on in this code? I don't seem to understand
how you can open the file and read it line by line instead of all of the sentences at the same time in a for loop. Thanks
Let's say I have these sentences in a document file:
cat:dog:mice
cat1:dog1:mice1
cat2:dog2:mice2
cat3:dog3:mice3
Here is the code:
from sys import argv
filename = input("Please enter the name of a file: ")
f = open(filename,'r')
d1ct = dict()
print("Number of times each animal visited each station:")
print("Animal Id Station 1 Station 2")
for line in f:
if '\n' == line[-1]:
line = line[:-1]
(AnimalId, Timestamp, StationId,) = line.split(':')
key = (AnimalId,StationId,)
if key not in d1ct:
d1ct[key] = 0
d1ct[key] += 1
The magic is at:
for line in f:
if '\n' == line[-1]:
line = line[:-1]
Python file objects are special in that they can be iterated over in a for loop. On each iteration, it retrieves the next line of the file. Because it includes the last character in the line, which could be a newline, it's often useful to check and remove the last character.
As Moshe wrote, open file objects can be iterated. Only, they are not of the file type in Python 3.x (as they were in Python 2.x). If the file object is opened in text mode, then the unit of iteration is one text line including the \n.
You can use line = line.rstrip() to remove the \n plus the trailing withespaces.
If you want to read the content of the file at once (into a multiline string), you can use content = f.read().
There is a minor bug in the code. The open file should always be closed. I means to use f.close() after the for loop. Or you can wrap the open to the newer with construct that will close the file for you -- I suggest to get used to the later approach.