Having trouble modifying python 2 code to python 3 - python-3.x

I've been trying to translate python 2.7 code to python 3. I believe everything above checkpoint 1 should be correct. But I'm getting an error I associated with the second half. I can always download the file I need straight from the link, but I'd like to know what's breaking here.
import urllib
from urllib.request import urlopen
import tarfile
import os
path = 'https://www.cs.cmu.edu/~./enron/enron_mail_20150507.tar.gz'
url = urlopen(path)
#checkpoint 1
os.chdir('..')
tfile = tarfile.open(url, "r:gz")
tfile.extractall(".")
Error:
Traceback (most recent call last):
File "startup.py", line 43, in <module>
tfile = tarfile.open(url, "r:gz")
File "/anaconda3/lib/python3.6/tarfile.py", line 1589, in open
return func(name, filemode, fileobj, **kwargs)
File "/anaconda3/lib/python3.6/tarfile.py", line 1636, in gzopen
fileobj = gzip.GzipFile(name, mode + "b", compresslevel, fileobj)
File "/anaconda3/lib/python3.6/gzip.py", line 163, in __init__
fileobj = self.myfileobj = builtins.open(filename, mode or 'rb')
TypeError: expected str, bytes or os.PathLike object, not HTTPResponse

When confronted with an error like this, closely look at the traceback, and read the documentation for the functions and objects involved.
urllib.request.urlopen returns a HTTPResponse object.
If you look at the error message, you see that tarfile.open expects a str, bytes or os.PathLike object for the parameter name.
However, tarfile.open supports using a file object as a third argument fileobj, and HTTPResponse implements the io.BufferedIOBase interface. The classes in io are basically the file objects that the open function returns.
So you should be able to do this:
tfile = tarfile.open(None, "r:gz", files)
or
tarfile.open(fileobj=url, mode="r:gz")
The latter could be considered more Pythonic ("explicit is better than implicit").

os.chdir('..')
tfile = tarfile.open("enron_mail_20150507.tar.gz", "r:gz")
Instead of doing the above two steps, can you just mention the fully qualified file name as parameter to tarfile.open? just to rule out the possibility that the path is incorrect

Related

How to randomly copy the contents of a text document to my clipboard

This is my original question
The following script copies the text in /home/my_files/document1.txt to my clipboard.
import pyperclip
path = '/home/my_files/document1.txt'
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Let's say /home/my_files/ contains the following five documents:
/home/my_files/document1.txt
/home/my_files/document2.txt
/home/my_files/document3.txt
/home/my_files/image1.jpg
/home/my_files/image2.png
I would like to create a script to randomly copy the contents of one of the three text documents in /home/my_files/ to my clipboard.
Of course the following script does not work but it shows some of the modules I've been experimenting with.
import glob,random,pyperclip
pattern = "*.txt"
path = random.choice((glob.glob(pattern))("/home/my_files/"))
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Do you have any relevant suggestions for me?
I added the subsequent content to my original question above
When I tried the following solution which #Jacob Lee created...
import glob
import random
import pyperclip
files = [os.path.abspath(f) for f in glob.glob("./home/my_files")]
path = random.choice(files)
with open(path) as f:
pyperclip.copy(f.read())
I received the following error message...
Traceback (most recent call last):
File "abc.py", line 3, in <module>
path = random.choice(glob.glob(pattern))
File "/usr/lib/python3.8/random.py", line 290, in choice
raise IndexError('Cannot choose from an empty sequence') from None
IndexError: Cannot choose from an empty sequence
Someone else suggested the following script to me...
import glob,random,pyperclip
pattern = "/home/my_files/*.txt"
path = random.choice(glob.glob(pattern))
print("copying contents of ", path)
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
But that script doesn't work either. I received the following error when I ran that script...
Traceback (most recent call last):
File "abc.py", line 3, in <module>
path = random.choice(glob.glob(pattern))
File "/usr/lib/python3.8/random.py", line 290, in choice
raise IndexError('Cannot choose from an empty sequence') from None
IndexError: Cannot choose from an empty sequence
I am confused.
The following successfully copies the entire contents of a random text file in /home/my_files/ to my clipboard
import glob,random,pyperclip
pattern = "/home/my_files/*.txt"
path = random.choice(glob.glob(pattern))
print("copying contents of ", path)
The_text_of_the_file_that_will_be_copied = open(path, 'r').read()
pyperclip.copy(The_text_of_the_file_that_will_be_copied)
Thanks to #Asocia
Thanks to #Asocia for insisting that the script above works correctly. I don't know what I had been doing wrong, but I must have been doing something wrong when I indicated the script above did not work properly.
You're code raises a TypeError: 'list' object is not callable exception when you try to assign path, in this line:
path = random.choice((glob.glob(pattern))("/home/my_files"))
glob.glob() returns a list (possibly empty). (Also, you put the glob.glob() call inside redundant parentheses.) Then, you try to call glob.glob()("/home/my_files/") (in essence, [...](), raising the TypeError exception.
import glob
import random
import pyperclip
files = [os.path.abspath(f) for f in glob.glob("./home/my_files/*.txt")]
path = random.choice(files)
with open(path) as f:
pyperclip.copy(f.read())

Is there a way to specify and then open a file with Python?

I'm attempting to make a program which will allow the user to pick a file from their computer and then open it. I've been trying to do this with Python, and...
filedialog.askopenfilenames()
...with this Tkinter widget.
I can get the filepath from this successfully, but how to I use it to actually open the file? (I'm trying to open it in its default app, not just print it to the Python console.) I've tried using
from subprocess import call
call(['xdg-open','filename'])
with 'files' (the variable that the filename is stored in) replacing 'filename', but I get the following error:
Traceback (most recent call last):
File "/Users/charlierubinstein/Documents/Search Engine.py", line 9, in <module>
call(['xdg-open', files])
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 267, in call
with Popen(*popenargs, **kwargs) as p:
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 709, in __init__
restore_signals, start_new_session)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/subprocess.py", line 1275, in _execute_child
restore_signals, start_new_session, preexec_fn)
TypeError: expected str, bytes or os.PathLike object, not tuple
my code so far:
from tkinter import *
from tkinter import ttk
from tkinter import filedialog
from subprocess import call
files = filedialog.askopenfilenames()
call(['xdg-open', files])
window.mainloop()
As stated earlier, ideally this program would let the user pick a file, and then open that file in its default app.
You use askopenfilenames() (with s at the end of name)
It let you select many files so it returns tuple with all selected files - even if you selected only one file
(or empty tuple if you cancel selection)
So you have to get first element from tuple
call(['xdg-open', files[0] ])
Or use askopenfilename() (without s at the end of name) and you will get single string.
filename = filedialog.askopenfilename() # without `s` at the end
call(['xdg-open', filename])

Proper Use Of Python 3.x AMFY Module

How am I supposed to use the Amfy module? I try to use it like the JSON module (amfy.loads or amfy.load), but it just gives me errors:
C:\Users\Other>"C:\Users\Other\Desktop\Python3.5.2\test amf.py"
Traceback (most recent call last):
File "C:\Users\Other\Desktop\Python3.5.2\test amf.py", line 4, in <module>
print(amfy.load(cn_rsp.text))
File "C:\Users\Other\Desktop\Python3.5.2\lib\site-packages\amfy\__init__.py", line 9, in load
return Loader().load(input, proto=proto)
File "C:\Users\Other\Desktop\Python3.5.2\lib\site-packages\amfy\core.py", line 33, in load
return self._read_item3(stream, context)
File "C:\Users\Other\Desktop\Python3.5.2\lib\site-packages\amfy\core.py", line 52, in _read_item3
marker = stream.read(1)[0]
AttributeError: 'str' object has no attribute 'read'
this is what I wrote:
import requests
import amfy
cn_rsp = requests.get("http://realm498.c10.castle.rykaiju.com/api/locales/en/get_serialized_new")
print(amfy.load(cn_rsp.text))
After tinkering around and googling some stuff, I found a fix:
New code:
import amfy, requests, json
url = "http://realm416.c9.castle.rykaiju.com/api/locales/en/get_serialized_static"
req = requests.get(url)
if req.status_code == 200:
ret = req.json() if "json" in req.headers["content-type"] else amfy.loads(req.content)
else:
ret = {"failed": req.reason}
with open ("doa manifest.txt", 'w', encoding = 'utf-8') as dump:
json.dumps(ret, dump)
The Terminal throws a UnicodeEncodeError, but I was able to fix that by entering chcp 65001 and then set PYTHONIOENCODING=utf-8
The load method expects an input stream, you provide it a string. Just convert your string into a memory buffer which supports read method like this:
import io
print(amfy.load(io.BytesIO(cn_rsp.text.encode())))
unfortunately serialization fails when using this. Is there another url where it would work, a test URL maybe?
File "C:\Python34\lib\site-packages\amfy\core.py", line 146, in _read_vli
byte = stream.read(1)[0]
IndexError: index out of range

Error when Unzipping with Pyside Qtgui

When I run my program, I get the following error and am not sure on how to correct it. Can someone help with explaining what this error is and how to correct it? Newb here so details are appreciated. Thanks for your time in advance!
Code:
#!/usr/bin/python
import zipfile
from PySide import QtGui
import re
#Select file to extract
app = QtGui.QApplication([])
dialog = QtGui.QFileDialog()
dialog.setFileMode(QtGui.QFileDialog.AnyFile)
if (dialog.exec()):
fileName = dialog.selectedFiles()
#Select Directory to extract to
dialog = QtGui.QFileDialog()
dialog.setFileMode(QtGui.QFileDialog.Directory)
dialog.setOption(QtGui.QFileDialog.ShowDirsOnly)
if (dialog.exec()):
dirName = dialog.selectedFiles()
print("Extracting.....")
zFile= zipfile.ZipFile(fileName)
zFile.extractall(dirName)
Error output:
Traceback (most recent call last):
File "C:\Users\Jennifer\Documents\BatchScripts\unzip.py", line 22, in <module>
zFile= zipfile.ZipFile(fileName)
File "C:\Python33\lib\zipfile.py", line 933, in __init__
self._RealGetContents()
File "C:\Python33\lib\zipfile.py", line 970, in _RealGetContents
endrec = _EndRecData(fp)
File "C:\Python33\lib\zipfile.py", line 237, in _EndRecData
fpin.seek(0, 2)
AttributeError: 'list' object has no attribute 'seek'
In your file and target directory code blocks, dialog.selectedFiles() returns a list. zipfile.ZipFile can only handle one file at a time, hence your error. To iterate over the list being provided by dialog.selectedFiles(), use the following:
for archive in fileName: # you should probably change it to fileNames to reflect its true nature
zfile = zipfile.ZipFile(archive)
print("Extracting " + str(zfile.filename) + "...")
zfile.extractall(dirName[0]) # also a list, extract to first item and ignore rest
and you should be all set.

AttributeError: 'module' object has no attribute 'urlretrieve'

I am trying to write a program that will download mp3's off of a website then join them together but whenever I try to download the files I get this error:
Traceback (most recent call last):
File "/home/tesla/PycharmProjects/OldSpice/Voicemail.py", line 214, in <module> main()
File "/home/tesla/PycharmProjects/OldSpice/Voicemail.py", line 209, in main getMp3s()
File "/home/tesla/PycharmProjects/OldSpice/Voicemail.py", line 134, in getMp3s
raw_mp3.add = urllib.urlretrieve("http://www-scf.usc.edu/~chiso/oldspice/m-b1-hello.mp3")
AttributeError: 'module' object has no attribute 'urlretrieve'
The line that is causing this problem is
raw_mp3.add = urllib.urlretrieve("http://www-scf.usc.edu/~chiso/oldspice/m-b1-hello.mp3")
As you're using Python 3, there is no urllib module anymore. It has been split into several modules.
This would be equivalent to urlretrieve:
import urllib.request
data = urllib.request.urlretrieve("http://...")
urlretrieve behaves exactly the same way as it did in Python 2.x, so it'll work just fine.
Basically:
urlretrieve saves the file to a temporary file and returns a tuple (filename, headers)
urlopen returns a Request object whose read method returns a bytestring containing the file contents
A Python 2+3 compatible solution is:
import sys
if sys.version_info[0] >= 3:
from urllib.request import urlretrieve
else:
# Not Python 3 - today, it is most likely to be Python 2
# But note that this might need an update when Python 4
# might be around one day
from urllib import urlretrieve
# Get file from URL like this:
urlretrieve("http://www-scf.usc.edu/~chiso/oldspice/m-b1-hello.mp3")
Suppose you have following lines of code
MyUrl = "www.google.com" #Your url goes here
urllib.urlretrieve(MyUrl)
If you are receiving following error message
AttributeError: module 'urllib' has no attribute 'urlretrieve'
Then you should try following code to fix the issue:
import urllib.request
MyUrl = "www.google.com" #Your url goes here
urllib.request.urlretrieve(MyUrl)

Resources