Redirect stdout to a text widget
I have searched and found some answers on redirecting the sys.stdout to a text widget in python, but I can't apply them to my specific needs.
I have coded a simple GUI with tkinter for a downloader found here and I want the stdout messages to appear on a text widget, which after much effort I couldn't achieve.
So let's make my case clearer with my code:
from Tkinter import*
import Tkinter as tk
import tkMessageBox
import urllib2
import sys
#functions
def downloadlinks():
# Configuration BEGIN
LOGIN = ''
PASSWORD = ''
USE_SSL = False
VERIFY_MD5SUM = False
# Configuration END
__version__ = '0.1.0'
import sys
import os
import urllib
import subprocess
import time
try:
import hashlib
md5 = hashlib.md5
except ImportError:
import md5
md5 = md5.new
def info(msg):
sys.stdout.write('\n%s\n\n' % msg)
sys.stdout.flush()
def error(msg):
sys.stderr.write('%s\n' % msg)
sys.stderr.flush()
sys.exit(1)
def transfer_progress(blocks_transfered, block_size, file_size):
percent = float((blocks_transfered * block_size * 100) / file_size)
progress = float(blocks_transfered * block_size / 1024)
downspeed = (float(blocks_transfered * block_size) / float(time.time() - starttime)) / 1024
sys.stdout.write("Complete: %.0f%% - Download开发者_如何学Goed: %.2fKb - Speed: %.3fkb/s\r" % (percent, progress, downspeed))
sys.stdout.flush()
def download(source, target):
global starttime
starttime = time.time()
filename, headers = urllib.urlretrieve(source, target, transfer_progress)
sys.stdout.write('Complete: 100%\n')
sys.stdout.flush()
for ss in headers:
if ss.lower() == "content-disposition":
filename = headers[ss][headers[ss].find("filename=") + 9:] # 9 is len("filename=")=9
urllib.urlcleanup() # Clear the cache
return filename
def verify_file(remote_md5sum, filename):
f = open(filename, "rb")
m = md5()
while True:
block = f.read(32384)
if not block:
break
m.update(block)
md5sum = m.hexdigest()
f.close()
return md5sum == remote_md5sum
def main():
file_link = "https://rapidshare.com/files/33392/examplefile.rar"
info('Downloading: %s' % file_link.split("/")[5])
try:
rapidshare_com, files, fileid, filename = file_link.rsplit('/')[-4:]
except ValueError:
error('Invalid Rapidshare link')
if not rapidshare_com.endswith('rapidshare.com') or files != 'files':
error('Invalid Rapidshare link')
if USE_SSL:
proto = 'https'
info('SSL is enabled00000000000')
else:
proto = 'http'
if VERIFY_MD5SUM:
info('MD5 sum verification is enabled')
info('Downloading: %s' % file_link.split("/")[5])
if filename.endswith('.html'):
target_filename = filename[:-5]
else:
target_filename = filename
info('Save file as: %s' % target_filename)
# API parameters
params = {
'sub': 'download_v1',
'fileid': fileid,
'filename': filename,
'try': '1',
'withmd5hex': '0',
}
if VERIFY_MD5SUM:
params.update({
'withmd5hex': '1',
})
if LOGIN and PASSWORD:
params.update({
'login': LOGIN,
'password': PASSWORD,
})
params_string = urllib.urlencode(params)
api_url = '%s://api.rapidshare.com/cgi-bin/rsapi.cgi' % proto
# Get the first error response
conn = urllib.urlopen('%s?%s' % (api_url, params_string))
data = conn.read()
#print data
conn.close()
# Parse response
try:
key, value = data.split(':')
except ValueError:
error(data)
try:
server, dlauth, countdown, remote_md5sum = value.split(',')
except ValueError:
error(data)
# Wait for n seconds (free accounts only)
if int(countdown):
for t in range(int(countdown), 0, -1):
sys.stdout.write('Waiting for %s seconds...\r' % t)
sys.stdout.flush()
time.sleep(1)
info('Waited for %s seconds. Proceeding with file download...' % countdown)
# API parameters for file download
dl_params = {
'sub': 'download_v1',
'fileid': fileid,
'filename': filename,
}
if LOGIN and PASSWORD:
dl_params.update({
'login': LOGIN,
'password': PASSWORD,
})
else:
dl_params.update({
'dlauth': dlauth,
})
dl_params_string = urllib.urlencode(dl_params)
download_link = '%s://%s/cgi-bin/rsapi.cgi?%s' % (proto, server, dl_params_string)
downloaded_filename = download(download_link, target_filename)
if VERIFY_MD5SUM:
if remote_md5sum.lower() == 'not found':
info('Remote MD5 sum is not available. Skipping MD5 sum verification...')
elif downloaded_filename:
if verify_file(remote_md5sum.lower(), downloaded_filename):
info('Downloaded and verified %s' % downloaded_filename)
else:
error('The downloaded file could not be verified')
else:
error('Will not verify. File not found: %s' % downloaded_filename)
info('Operation Complete')
if __name__ == '__main__':
try:
main()
except KeyboardInterrupt:
error('\nAborted')
tkMessageBox.showinfo('Download Status Notification',"All files have been downloaded.")
#Window Title
app=Tk()
app.title("Downloader")
app.geometry('700x1080+550+0')
app.resizable(0,0)
#Title
titleText = StringVar()
titleText.set("Downloader")
label0=Label(app,textvariable=titleText,font=("Times", 16,"bold"),height=2)
label0.pack()
#
f1 = Frame(app, width=600, height=200)
xf1 = Frame(f1, relief=RAISED, borderwidth=5)
#Text
labelText = StringVar()
labelText.set("Enter link:")
label1=Label(f1,textvariable=labelText,font=("Times", 14))
label1.pack(side=LEFT, padx=5,pady=8)
#Field
linkname = StringVar(None)
linkname1 =Entry(f1,textvariable = linkname,font=("Times", 14),justify=CENTER)
linkname1.pack(side=LEFT, padx=5,pady=8)
Label(f1, text='').place(relx=1.06, rely=0.125,anchor=CENTER)
f1.pack()
#Button
downloadbutton=Button(app,text="Download",font=("Times", 12, "bold"),width=20,borderwidth=5,foreground = 'white',background = 'blue',command=downloadlinks)
downloadbutton.pack()
#####
downloadmessages = Text(app,height = 6,width=80,font=("Times", 12),foreground = 'cyan',background='black' )
downloadmessages.insert(END,"")
downloadmessages.pack(padx=20,pady=1)
app.mainloop()
So,let me ask some questions.My code descriptively is like that :
-import modules
-def downloadlinks()
-Window Title
-Title
-Frame with : Text Field
-Button
-Text Widget
When it says my_frame = your_gui_code_here()
, does it refer to the Text Widget Code ?
downloadmessages = Text(app,height = 6,width=80,font=("Times", 12),foreground = 'cyan', background='black' )
downloadmessages.insert(END,"")
downloadmessages.pack(padx=20,pady=1)
You would need to open it as a subprocess and then pipe the stdout from there to a writeable source.
e.g.
import subprocess
my_frame = your_gui_code_here()
process = subprocess.Popen('ls', stdout=subprocess.PIPE, stderr=subprocess.PIPE)
my_frame.add_text(process.communicate()[0]) #or however you add text.
精彩评论