argparse and filetypes

48 views
Skip to first unread message

Bradley Hintze

unread,
Mar 22, 2011, 10:06:41 AM3/22/11
to Python
Hi,

I just started with argparse. I want to simply check the extension of
the file that the user passes to the program. I get a ''file' object
has no attribute 'rfind'' error when I use
os.path.splitext(args.infile). Here is my code.

import argparse, sys, os

des = 'Get restraint definitions from probe.'
parser = argparse.ArgumentParser(description=des)
parser.add_argument('infile', nargs='?', type=argparse.FileType('r'))
# parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
# default=sys.stdout)

args = parser.parse_args()
# print args.infile.readlines()
print basename, extension = os.path.splitext(args.infile)

There may be a better way to check extensions using argparse.

Any help will be appreciated.
Thanks,
Bradley

--
Bradley J. Hintze
Graduate Student
Duke University
School of Medicine

Alex Willmer

unread,
Mar 22, 2011, 10:48:42 AM3/22/11
to
On Mar 22, 2:06 pm, Bradley Hintze <bradle...@aggiemail.usu.edu>
wrote:

> I just started with argparse. I want to simply check the extension of
> the file that the user passes to the program. I get a ''file' object
> has no attribute 'rfind'' error when I use
> os.path.splitext(args.infile).  Here is my code.
>
> import argparse, sys, os
>
> des = 'Get restraint definitions from probe.'
> parser = argparse.ArgumentParser(description=des)
> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'))
> # parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
>                    # default=sys.stdout)
>
> args = parser.parse_args()
> # print args.infile.readlines()
> print basename, extension = os.path.splitext(args.infile)

Because you specified type=argparse.FileType('r') argparse has created
args.infile as a file object (e.g. open('/some/path/data.dat', 'r')),
not as a string containing the path. So type(args.infile) ==
type(file) and args.infile.readlines() returns the contents of that
file.

If you wish to check the file extension of the path in question I
suggest you remove type=argparse.FileType('r'), argparse will create
args.infile as a string containing that path. To open the file call
open(args.infile, 'r'), this will return the file object.

Alex Willmer

unread,
Mar 22, 2011, 11:52:37 AM3/22/11
to
On Mar 22, 2:06 pm, Bradley Hintze <bradle...@aggiemail.usu.edu>
wrote:
> Hi,
>
> I just started with argparse. I want to simply check the extension of
> the file that the user passes to the program. I get a ''file' object
> has no attribute 'rfind'' error when I use
> os.path.splitext(args.infile).

Addendum, some file objects have a name attribute (which I hadn't
noticed until today):

file.name
If the file object was created using open(), the name of the file.
Otherwise, some string that indicates the source of the file object,
of the form <...>. This is a read-only attribute and may not be
present on all file-like objects.

http://docs.python.org/library/stdtypes.html#file-objects

Robert Kern

unread,
Mar 22, 2011, 2:09:09 PM3/22/11
to pytho...@python.org
On 3/22/11 9:06 AM, Bradley Hintze wrote:
> Hi,
>
> I just started with argparse. I want to simply check the extension of
> the file that the user passes to the program. I get a ''file' object
> has no attribute 'rfind'' error when I use
> os.path.splitext(args.infile). Here is my code.
>
> import argparse, sys, os
>
> des = 'Get restraint definitions from probe.'
> parser = argparse.ArgumentParser(description=des)
> parser.add_argument('infile', nargs='?', type=argparse.FileType('r'))
> # parser.add_argument('outfile', nargs='?', type=argparse.FileType('w'),
> # default=sys.stdout)
>
> args = parser.parse_args()
> # print args.infile.readlines()
> print basename, extension = os.path.splitext(args.infile)
>
> There may be a better way to check extensions using argparse.

The type= argument should be a callable that either coerces the string to an
appropriate object or raises a ValueError if the string is unacceptable.
FileType() is a convenient callable for opening readable or writable files; when
called, it returns a regular file object, not the filename, as you saw from the
exception you got. It does not do any validation.

You can add validation very easily:

class TxtFile(argparse.FileType):
def __call__(self, string):
base, ext = os.path.splitext(string)
if ext != '.txt':
raise ValueError('%s should have a .txt extension' % string)
return super(TxtFile, self).__call__(string)

...
parser.add_argument('infile', type=TxtFile('r'))

--
Robert Kern

"I have come to believe that the whole world is an enigma, a harmless enigma
that is made terrible by our own mad attempt to interpret it as though it had
an underlying truth."
-- Umberto Eco

Reply all
Reply to author
Forward
0 new messages