I'm working through the "Learn python the hard way" book, I've run into a problem in the Second Exercise of the 16th study drill. I am using the newest version of python 3.
The code I wrote looks like this so far:
from sys import argv
script, filename = argv #we input the filename into argv
print ("We're going to erase %r." % filename) #tells us the name of the file we're deleting
print ("If you don't want that, hit CTRL-C (^C)")
print ("If you do want that, hit RETURN.")
input("?") #look into error unexpected EOF while parsing, I had to type "", if I don't program ends here
print ("Opening the file...")
target = open(filename, "w") #opens the file
print ("Truncating the file. Goodbye!")
target.truncate() #erases everything in the file
print ("Now I'm going to ask you for three lines")
line1 = input("line 1: ")
line2 = input("line 2: ")
line3 = input("line 3: ")
#summary: we create 3 input variables we'll use under here
print ("I'm going to write these to the file.")
target.write(line1) #summary: we write in the terminal what we want in our file and use that
target.write("\n") #we also have this newline command after every line to make sure it's not all in one line
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
#The default code is done at this point
print ("Type the filename again and I'll read it back to you or press CTRL + C (^C) to exit")
file_again = input(">")
print (file_again) #Added to try to see what this gave me, it gives nothing back --- isn't working, why?
print ("Now I'll read the file back to you!") #This prints
text_again = open(file_again) #Not sure if this is working
print (text_again.read()) #Is doing nothing in the Terminal
print("And finally we close the file") #Works
target.close()
At this point I'm wondering why the stuff after "#The default code is done at this point" is not working, I ripped it exactly as-is from another program (Exercise 15 of the same book), my Command line looks like this:
C:\PATH\Study Drills>py SD8.py "test.txt"
We're going to erase 'test.txt'.
If you don't want that, hit CTRL-C (^C)
If you do want that, hit RETURN.
?""
Opening the file...
Truncating the file. Goodbye!
Now I'm going to ask you for three lines
line 1: "Hey"
line 2: "yo"
line 3: "sup"
I'm going to write these to the file.
Type the filename again and I'll read it back to you or press CTRL + C (^C) to exit
>"test.txt"
Now I'll read the file back to you!
BONUS QUESTION: In the point where I say ("#look into error unexpected EOF while parsing, I had to type "", if I don't program ends here") why do I have to put quotation marks? If I don't the program ends with the error message mentioned in the comment.
Once you're done with all your write calls, close() the file. Due to things like OS buffering, the data is not guaranteed to be actually written to the file until you close the file object (which is done automatically when you exit the program, as you might have noticed -- kill your program and the data will be in the file).
In addition, your truncate call is unnecessary -- opening a file in "w" mode immediately truncates it.
Related
I am trying to brute-force a python program:
what I need is to make another python file that will run
the first python code with an input (The first code takes input with raw_input)
The problem is that the first code uses pygame, so if I want to brute-force I need to run it, try a number, then open it again, and continue checking like that...
do you have any idea how to write to a process raw_input like a bruteforce?
This is a lite version of what I'm trying to do: (without pygame)
first code: (The one I need to bruteforce)
found = []
while 1:
a =int(raw_input("ENTER : "))
print "THE NUM: ", a
if a in [74,82,101,550,990]:
print a , " Got number right!"
found.append(a)
if [74,82,101,550,990] == found:
print "WINNER!!!!!"
break
This one does not have pygame, but the idea stays the same..
I tried using this code:
import subprocess
for i in range(1000):
process = subprocess.Popen(["grep", "PATH TO PYCODE"],
stdin=subprocess.PIPE, stdout=subprocess.PIPE)
process.stdin.write(i)
print process.communicate()[0]
process.stdin.close()
But it gives this error:
WindowsError: [Error 2] The system cannot find the file specified
and the path is 100% correct...
Edit:
if I write in cmd:
echo 5 | python PATH_TO_FILE
it pops this error:
EOFError: EOF when reading a line
Thanks for helping! :)
You have several issues.
First, the top program (which I'll call check.py) doesn't terminate on EOF, it throws an error. Second, the top program is written to be interactive but you're using it noninteractively. Removing the "INPUT : " should be enough to fix this for your purposes.
Try this:
import sys
found = []
for line in sys.stdin:
line = line.strip();
a = int(line);
print "THE NUM: ", a
if a in [74,82,101,550,990]:
print a , " Got number right!"
found.append(a)
if [74,82,101,550,990] == found:
print "WINNER!!!!!"
break
Third, the bottom program will never be the WINNER because it restarts the program for each guess. Fourth, you're writing binary values into the pipe, but your program expects text.
import subprocess
process = subprocess.Popen(["python", "check.py"], stdin=subprocess.PIPE, stdout=subprocess.PIPE)
for i in range(1000):
process.stdin.write("%d\n" % i)
print process.communicate()[0]
process.stdin.close()
Before running this you probably want to delete "THE NUM" printout from check.py.
However, your initial question did say that you need to restart the pygame each time, so in that case you would leave the loop on i as you had it originally -- that's just not what your example program is written to expect.
Here's the output, with the "THE NUM : " output commented out:
$ python pipe.py
74 Got number right!
82 Got number right!
101 Got number right!
550 Got number right!
990 Got number right!
WINNER!!!!!
This is from exercise 16 from Zed Shaw's Python tutorials. I'm having a hard time understanding what exactly the truncate function does in this case. So the logic is that we open a file and then...shorten it? For what? What exactly is happening here?
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."
raw_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 = raw_input("line 1: ")
line2 = raw_input("line 2: ")
line3 = raw_input("line 3: ")
print "I'm going to write these to the file."
target.write(line1 + "\n" + line2 + "\n" + line3 + "\n")
print "And finally, we close it."
target.close()
You're right to be suspicious.
First, file.truncate does this:
Truncate the file’s size. If the optional size argument is present, the file is truncated to (at most) that size. The size defaults to the current position…
Not quite the same as Zed's description—it only "empties the file" if the current position is the start of the file—but since we just opened the file (and not in a mode), the current position is the start, so that isn't relevant. We're truncating to an empty file.
Which is all well and good, except that open already does that:
The most commonly-used values of mode are 'r' for reading, 'w' for writing (truncating the file if it already exists) …
So, we open the file, creating it if it doesn't exist and truncating it to 0 bytes if it does. Then, on the next line, we truncate it to 0 bytes.
(That "Truncating the file. Goodbye!" message is pretty misleading, since we've already truncated it. Imagine you put a breakpoint on that line and decided to kill the program before executing it…)
But notice that this isn't some silly mistake by Zed; he appears to have done this specifically to make the point in study drill #5:
If you open the file with 'w' mode, then do you really need the target.truncate()? Read the documentation for Python's open function and see if that's true.
I am currently going through Zed Shaw's book to. Often. when he gives you problems like these, he is goading you into messing around with the different elements of your code to see what they do. Feel free to delete things like target.truncate() and re-run the program. As abarnert says, there is a way to make truncate only remove a portion of the file. Leaving this hole in your knowledge, as to how to get different results with these two options, is meant to annoy you into doing some independent research. It's a very effective way of infecting the reader with curiosity. Take a look how append works in Python and see if you can make truncate() remove only the last line of your test file. Don't be afraid to break your code. "If you want to increase your success rate, double your failure rate." (Thomas J. Watson, former CEO of IBM)
I am trying to use Pastebin to host two text files for me to allow any copy of my script to update itself through the internet. My code is working, but the resultant .py file has a blank line added between each line. Here is my script...
import os, inspect, urllib2
runningVersion = "1.00.0v"
versionUrl = "http://pastebin.com/raw.php?i=3JqJtUiX"
codeUrl = "http://pastebin.com/raw.php?i=GWqAQ0Xj"
scriptFilePath = (os.path.abspath(inspect.getfile(inspect.currentframe()))).replace("\\", "/")
def checkUpdate(silent=1):
# silently attempt to update the script file by default, post messages if silent==0
# never update if "No_Update.txt" exists in the same folder
if os.path.exists(os.path.dirname(scriptFilePath)+"/No_Update.txt"):
return
try:
versionData = urllib2.urlopen(versionUrl)
except urllib2.URLError:
if silent==0:
print "Connection failed"
return
currentVersion = versionData.read()
if runningVersion!=currentVersion:
if silent==0:
print "There has been an update.\nWould you like to download it?"
try:
codeData = urllib2.urlopen(codeUrl)
except urllib2.URLError:
if silent==0:
print "Connection failed"
return
currentCode = codeData.read()
with open(scriptFilePath.replace(".py","_UPDATED.py"), mode="w") as scriptFile:
scriptFile.write(currentCode)
if silent==0:
print "Your program has been updated.\nChanges will take effect after you restart"
elif silent==0:
print "Your program is up to date"
checkUpdate()
I stripped the GUI (wxpython) and set the script to update another file instead of the actual running one. The "No_Update" bit is for convenience while working.
I noticed that opening the resultant file with Notepad does not show the skipped lines, opening with Wordpad gives a jumbled mess, and opening with Idle shows the skipped lines. Based on that, this seems to be a formatting problem even though the "raw" Pastebin file does not appear to have any formatting.
EDIT: I could just strip all blank lines or leave it as is without any problems, (that I've noticed) but that would greatly reduce readability.
Try adding the binary qualifier in your open():
with open(scriptFilePath.replace(".py","_UPDATED.py"), mode="wb") as scriptFile:
I notice that your file on pastebin is in DOS format, so it has \r\n in it. When you call scriptFile.write(), it translates \r\n to \r\r\n, which is terribly confusing.
Specifying "b" in the open() will cause scriptfile to skip that translate and write the file is DOS format.
In the alternative, you could ensure that the pastebin file has only \n in it, and use mode="w" in your script.
I have a script which executes some command using os.popen4. Problem is some time command being executed will require user input ("y" or "n"). I am reading stdout/stderr and printing it, but it seems question from command doesn't got printed and it hangs. To make it work, i had to write "n" to stdin blindly. Can some one please guide on how to handle it?
Code not working:
(f_p_stdin, f_p_stdout_stderr) = os.popen4(cmd_exec,"t")
cmd_out = f_p_stdout_stderr.readlines()
print cmd_out
f_p_stdin.write("n")
f_p_stdin.close()
f_p_stdout_stderr.close()
Working Code:
(f_p_stdin, f_p_stdout_stderr) = os.popen4(cmd_exec,"t")
cmd_out = f_p_stdout_stderr.readlines()
f_p_stdin.write("n")
f_p_stdin.close()
print cmd_out
f_p_stdout_stderr.close()
NOTE : I am aware that it is depreciated and subprocess module is used, but right now i don't know on how to use it. So i'll appreciate if some one will help me to handle it using os.popen4. I want to capture the question and handle the input from user and execute it.
readlines() : returns a list containing all the lines of data in the file. If reading from a process like in this case, there is a good chance it does not send a newline and/or flush the output. You should read characters from the input and process that to see if the question was posed.
It would help to know what cmd_exec looks like, so others can try and emulate what you tried.
Update:
I wrote a uncheckout command in Python:
#! /usr/bin/env python
# coding: utf-8
import sys
print 'Uncheckout of {} is irreversible'.format(sys.argv[1])
print 'Do you want to proceed? [y/N]',
sys.stdout.flush()
x = raw_input()
if x == 'y':
print sys.argv[1], "no longer checked out"
else:
print sys.argv[1], "still checked out"
I put the prompt string on purpose not as argument to raw_input, to be able to do the flush() explicitly.
Neither of your code snippets work with that (assuming cmd_exec to be ['./uncheckout', 'abc.txt'] or './uncheckout abc.txt', popen4() uses the shell in the latter case to start the program).
Only when I move the readlines() until after the write() and close() will the command continue.
That makes sense to me as the close() flushes the output. You are writing in text mode and that buffers normally until end-of-line, which is not in your .write('n').
To be able to check what the prompt is and test and react on that., the following works with the above uncheckout:
#! /usr/bin/env python
# coding: utf-8
import os
import sys
cmd_exec = ['./uncheckout', 'abc.txt']
(f_p_stdin, f_p_stdout_stderr) = os.popen4(cmd_exec,"t")
line = ''
while True:
x = f_p_stdout_stderr.read(1)
if not x:
break
sys.stdout.write(x)
sys.stdout.flush()
if x == '\n':
line = ''
else:
line += x
if line.endswith('[y/N]'):
f_p_stdin.write("n\n")
f_p_stdin.flush()
sys.stdout.write('\n')
Maybe you can work backwards from that to make something that works for you. Make sure to keep flushes at appropriate places.
Is there a simple module that let's you paste input in python ?
Asking someone to type letter by letter is kinda harsh .
By default a .py file is opened with python.exe if is installed and this does not allow "rightclick+paste" in the console .So how can i make this happen with python ? i think this would be more of a exact question .
You can make this by open cmd.exe and type here "C:\Python32\python".
Path is depend on the version of python. Mine is 3.2.
If you're looking for a way to simply paste something into the windows command prompt, John Giotta is correct that a user can click on the little icon in the top left.
I imagine, however, that you're looking for a way that a user can input a large amount of text, without typing it in line by line. A simple way to do this, would be to let the user input a file name, which python would then read. Perhaps something like this is what you're looking for:
while True:
filename = raw_input("Path to file to be read: ")
try:
with open(filename, 'rb') as f:
contents = f.read()
break
except IOError:
print "That was not a valid file \n"
This loop will keep asking the user for a file until then enter a valid path. When they enter a valid path, it will be read in as a string to the contents variable. This way, a user could enter a large amount of text into a file, and then you simply prompt them for the path to the file.
You can read up on file input more In the docs.