I am trying to write a python program that will eventually take a command line argument of a file, determine if its a tar or zip etc file and then exctract it accordingly. I am just trying to get the tar part working now and I am getting multiple errors. The file I am checking for resides in my ~/ directory. Any ideas would be great.
#!/usr/bin/python
import tarfile
import os
def open_tar(file):
if tarfile.is_tarfile(file):
try:
tar = tarfile.open("file")
tar.extractall()
tar.close()
except ReadError:
print "File is somehow invalid or can not be handled by tarfile"
except CompressionError:
print "Compression method is not supported or data cannot be decoded"
except StreamError:
print "Is raised for the limitations that are typical for stream-like TarFile objects."
except ExtractError:
print "Is raised for non-fatal errors when using TarFile.extract(), but only if TarFile.errorlevel== 2."
if __name__ == '__main__':
file = "xampp-linux-1.7.3a.tar.gz"
print os.getcwd()
print file
open_tar(file)
Here are the errors. IF I comment out the Read Error, I just get teh same error on the next exception as well.
tux#crosnet:~$ python openall.py
/home/tux
xampp-linux-1.7.3a.tar.gz
Traceback (most recent call last):
File "openall.py", line 25, in <module>
open_tar(file)
File "openall.py", line 12, in open_tar
except ReadError:
NameError: global name 'ReadError' is not defined
tux#crosnet:~$
You can clearly see in your error it states
NameError: global name 'ReadError' is not defined
ReadError is not a global python name. If you look at the tarfile documentation you will see ReadError is part of that modules exceptions. So in this case, you would want to do:
except tarfile.ReadError:
# rest of your code
And you will need to do the same for the rest of those errors. Also, if all those errors will generate the same result (an error message of some sort, or a pass) you can simply do:
except (tarfile.ReadError, tarfile.StreamError) # and so on
Instead of doing them each on a seperate line. That's only if they will give the same exception
You would need to use except tarfile.ReadError or alternatively use from tarfile import is_tarfile, open, ReadError, CompressionError, etc. and put that inside the open_tar function instead of globally.
I think you might need tarfile.ReadError rather than just ReadError?
Okay. All your exceptions (ReadError, CompressionError etc.) are inside the tarfile module and so you'll have to say except tarfile.ReadError instead of just except ReadError.
Related
I recently made a program using an external document with pickle. But when it tries to load the file with pickle, I got this error (the file is already existing but it also fails when the file in't existing):
python3.6 check-graph_amazon.py
a
b
g
URL to follow www.amazon.com
Product to follow Pool_table
h
i
[' www.amazon.com', ' Pool_table', []]
p
Traceback (most recent call last):
File "check-graph_amazon.py", line 17, in <module>
tab_simple = pickle.load(doc_simple)
io.UnsupportedOperation: read
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "check-graph_amazon.py", line 42, in <module>
pickle.dump(tab_simple, 'simple_data.dat')
TypeError: file must have a 'write' attribute
Here is the code :
import pickle5 as pickle
#import os
try:
print("a")
with open('simple_data.dat', 'rb') as doc_simple:
print("b")
tab_simple = pickle.load(doc_simple)
print("c")
print(tab_simple)
print("d")
URL = tab_simple[0]
produit_nom = tab_simple[1]
tous_jours = tab_simple[2]
print("f")
except :
print("g")
URL = str(input("URL to follow"))
produit_nom = str(input("Product to follow"))
with open('simple_data.dat', 'wb+') as doc_simple:
print("h")
#os.system('chmod +x simple_data.dat')
tab_simple = []
tab_simple.append(URL)
tab_simple.append(produit_nom)
tab_simple.append([])
print(tab_simple)
print("c'est le 2")
print("p")
pickle.dump(tab_simple, 'simple_data.dat')
print("q")
The prints are here to show which lines are executed. The os.system is here to allow writing on the file but the error is persisting.
I don't understand why it's said that the document doesn't have a write attribute because I opened it in writing mode. And I neither understand the first error where it can't load the file.
If it can help you the goal of this script is to initialise the program, with a try. It tries to open the document in reading mode in the try part and then set variables. If the document doesn't exist (because the program is lauched for the first time) it goes in the except part and create the document, before writing informations on it.
I hope you will have any clue, including changing the architecture of the code if you have a better way to make an initialisation for the 1st time the program is launched.
Thanks you in advance and sorry if the code isn't well formated, I'm a beginner with this website.
Quote from the docs for pickle.dump:
pickle.dumps(obj, protocol=None, *, fix_imports=True)
Write a pickled representation of obj to the open file object file. ...
...
The file argument must have a write() method that accepts a single bytes argument. It can thus be an on-disk file opened for binary writing, an io.BytesIO instance, or any other custom object that meets this interface.
So, you should pass to this function a file object, not a file name, like this:
with open("simple_data.dat", "wb"): as File:
pickle.dump(tab_simple, File)
Yeah, in your case the file has already been opened, so you should write to doc_simple.
Im creating a DOS clone with python and I have a command cd which allows you to change directory. The only problem is that if you misspell or type a non-existent directory, the program closes with a traceback error. Im basically looking for it not to completely close the program but instead print a statement like 'requested_directory' Is not a directory! and allow you to type in a different directory.
Ive tried a couple things, mainly error handling, but to no prevail. Im assuming that im still not quite understanding error handling or using it incorrectly.
Any help is much appreciated.
This is the code im using to change directories (elif because i have many more commands. cmd is a raw input.)
elif 'cd' in cmd:
desired_directory = cmd.split(' ')[1]
if desired_directory == "..":
os.chdir('..')
else:
os.chdir(desired_directory)
This is the output when an incorrect directory is typed in
Traceback (most recent call last):
File "/Users/jrosmac/PycharmProjects/untitled/JDOS/SYS64/jdosos.py", line 47, in <module>
os.chdir(desired_directory)
OSError: [Errno 2] No such file or directory: 'raw_input goes here'
I believe you need to handle the error.
try:
os.chdir(desired_directory)
except OSError as e:
print e.args[0]
Use exception handing:
try:
os.chdir(target)
except OSError as e:
# handle the failure of the chdir call
I can't seem to generate this exception with python code with a genuine error.
I used the code from this question to check my work. Here it is, modified only slightly:
import py_compile
def check(python_file):
try:
file = open(python_file, 'r')
py_compile.compile(python_file, doraise=True)
except py_compile.PyCompileError:
print("<"+python_file+"> does not contain syntactically correct Python code")
else:
print("Compiled " + python_file + " with no issues.")
check("example.py")
The file example.py contains just:
print ("This is fine.")
prant ("This should be an error.")
'prant' instead of 'print' would be a simple syntax error, and if I run 'python example.py' then I see:
This is fine.
Traceback (most recent call last):
File "example.py", line 2, in <module>
prant ("This should be an error.")
NameError: name 'prant' is not defined
If I call the script at the top 'compiler.py' and then run 'python compiler.py' it will say there are no issues.
I have verified that compiler.py will complain about syntactic correctness if there are unmatched parentheses or quotes, so it does catch some problems. But I would like to be able to detect when a file has errors in the same way that running 'python example.py' or whatever would do. Basically, if it has an error when running it with 'python', I'd like to be able to detect that.
Is there a way to do this? And why is PyCompileError not being thrown when there is a syntax error?
I'm sure that the answer for this is out there, but I've read the site info, I've watched the video they made and I've tried to find a really basic tutorial but I can't. I've been messing about with this for most of the day and It's not really making sense to me.
Here's my error:
vco#geoHP:~$ python3 a_blah.py "don't scare the cats" magic
Traceback (most recent call last):
File "a_blah.py", line 20, in <module>
arguments = docopt.docopt(__doc__)
File "/usr/lib/python3/dist-packages/docopt.py", line 579, in docopt
raise DocoptExit()
docopt.DocoptExit: Usage:
a_blah.py <start>... <end>
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "a_blah.py", line 33, in <module>
except DocoptExit:
NameError: name 'DocoptExit' is not defined
line 20 - I don't see why that line is creating an error, it worked before and I've seen that exact line in others programmes?
I don't know why the line 570 of docopt is creating an error - I've seen others use DocoptExit(), isn't this something that's just part of Docopt? Do I have to write my own exit function for this? (I've not seen anyone else do that)
here's the code
import docopt
if __name__ == '__main__':
try:
arguments = docopt.docopt(__doc__)
print(arguments['<start>'])
print("that was that")
print(arguments['<end>'])
except docopt.DocoptExit:
print("this hasn't worked")
What I'm trying to make this for is a script that I've written that moves files from one place to another based on their extension.
So the arguments at the command line will be file type, start directory, destination directory, and an option to delete them from the start directory after they've been moved.
I'm trying (and failing) to get docopt working on it's own prior to including it in the other script though.
The exception you want is in docopt's namespace. You never import it into your global namespace, so you can't refer to it simply with it's name. You need to import it separately or refer to it through the module. You also shouldn't use parenthesis after the exception.
import docopt
try:
# stuff
except docopt.DocoptExit:
# other stuff
or
import docopt
from docopt import DocoptExit
try:
# stuff
except DocoptExit:
# other stuff
I'm using Fabric to automate, including the task of creating a directory. Here is my fabfile.py:
#!/usr/bin/env python
from fabric.api import *
def init():
try:
local('mkdir ./www')
except ##what exception?##:
#print exception name to put in above
Run fab fabfile.py and f I already have ./www created an error is raised, but I don't know what kind, so I don't know how to handle the error yet. Fabric only prints out the following:
mkdir: cannot create directory ‘./www’: File exists
Fatal error: local() encountered an error (return code 1) while executing 'mkdir ./www'
Aborting.
What I want to do is be able to find out the error type so that I can except my errors properly without blanket statements. It would be really helpful if an answer does not just tell me how to handle a mkdir exception, but print (or otherwise find the name to) any exception I may run into down the line (mkdir is just an example).
Thank you!
The issue is that fabric uses subprocess for doing these sorts of things. If you look at the source code for local you can see it doesn't actually raise an exception. It calls suprocess.Popen and uses communicate() to read stdout and stderr. If there is a non-zero return code then it returns a call to either warn or abort. The default is abort. So, to do what you want, try this:
def init():
with settings(warn_only=True):
local('mkdir ./www')
If you look at the source for abort, it looks like this:
10 def abort(msg):
21 from fabric.state import output
22 if output.aborts:
23 sys.stderr.write("\nFatal error: %s\n" % str(msg))
24 sys.stderr.write("\nAborting.\n")
25 sys.exit(1)
So, the exception would be a SystemExit exception. While you could catch this, the proper way to do it is outlined above using settings.
It is nothing to handle with exception, it is from the fabric api
try to set the entire script's warn_only setting to be true with
env.warn_only = True
Normally, when you get an uncaught exception, Python will print the exception type along with the error message:
>>> raise IOError("Error message.")
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
IOError: Error message.
If that's not happening, you're probably not getting an exception at all.
If you really want to catch an arbitrary exception and print it, you want to catch Exception or BaseException. BaseException will include even things like KeyboardInterrupt, though, so be careful with that.
def init():
try:
local('mkdir ./www')
except BaseException as e:
print "local() threw a", type(e).__name__
raise # Reraise the exception
In general:
try:
some_code()
except Exception, e:
print 'Hit An Exception', e
raise
Will tell you what the exception was but if you are not planning on actually handling some of the exceptions then simply getting rid of the try: except: lines will have exactly the same effect.
Also if you run your code under a debugger then you can look at the exception(s) that you hit in more detail.
def init():
try:
local('mkdir ./www')
except Exception as e:
print e.__class__.__name__
That's all there is to it!
edit: Just re-read your question and realized that my code would only print "Fatal" in your case. It looks like fabric is throwing an error and returning their own error code so you would have to look at the documentation. I don't have any experience with fabric so I'd suggest to look here if you haven't already. Sorry if this isn't helpful!