views:

466

answers:

6

I updated my python interpreter, but I think the old one is still called. When I check for the version I get:

$ python -V
Python 3.0.1

But I believe the old interpreter is still being called. When I run the command:

python myProg.py

The script runs properly. But when I invoke it with the command

./myProg.py

I get the error message:

AttributeError: 'str' object has no attribute 'format'

Which apparently is due to the old interpreter being called. How can I fix this? I run Mac OS X 10.5. Has it something to do with the first line:

#!/usr/bin/python

I just started out with python and am not very familiar with interpreted languages, so I am not too sure what is going on.

Edit: Wow, that was quick. Thanks a lot!

+2  A: 

run 'which python' - if this gives a different answer than /usr/bin/python, change #!/usr/bin/python to have that path instead.

Nathaniel Flath
+3  A: 

Try which python. I will tell you which python interpreter is used in your environment. If it is not /usr/bin/python like in the script, then your suspicion is confirmed.

bbuser
+9  A: 

According to the first line of the script, #!/usr/bin/python, you are calling the Python interpreter at /usr/bin/python (which is most likely the one that ships with Mac OS X). You have to change that path to the path where you installed your Python 3 interpreter (likely /usr/local/bin/python or /opt/local/bin/python); or you can just change that line to read #!/usr/bin/env python, which will call the python listed first in your PATH variable (which seems to be the newer version you installed).

mipadi
+5  A: 

Firstly, the recommended shebang line is:

#!/usr/bin/env python

This will make sure the python interpreter that is invoked when you ./foo.py is the same interpreter that is invoked when you invoke python from the command line.

From your description, I suspect that if you did:

which python

It would not give you /usr/bin/python. It would give you something else, which is where the python 3 interpreter lives. You can either modify your shebang line to the above, or replace the path to the python interpreter with the path returned by which.

freespace
+2  A: 

It's very possibly what you suspect, that the shebang line is calling the older version. Two things you might want to check:

1) what version is the interpreter at /usr/bin/python:

/usr/bin/python -V

2) where is the python 3 interpreter you installed:

which python

If you get the correct one from the command line, then replace your shebang line with this:

#!/usr/bin/env python

Addendum: You could also replace the older version of python with a symlink to python 3, but beware that any major OS X updates (ie: 10.5.6 to 10.5.7) will likely break this:

sudo mv /usr/bin/python /usr/bin/python25
sudo ln -s /path/to/python/3/python /usr/bin/python
EvanK
It's probably not the best idea to replace /usr/bin/python with a symlink. Some OS X utilities may refer to /usr/bin/python, and since Python 3K is not 100% backwards-compatible with Python 2.x, you run the risk of breaking some of those utilities.
mipadi
Yeah, I'd recommend against messing with the Python that comes with OS X.
Jason Baker
A: 

It may be a bit odd providing a Perl script to answer a Python question, but it works for Python just as well as it does for Perl. This is a script called 'fixin', meaning 'fix interpreter'. It changes the shebang line to the correct string for your current PATH.

#!/Users/jleffler/perl/v5.10.0/bin/perl
#
#   @(#)$Id: fixin.pl,v 1.3 2003/03/11 21:20:08 jleffler Exp $
#
#   FIXIN: from Programming Perl
#   Usage: fixin [-s] [file ...]

# Configuration
$does_hashbang = 1;  # Kernel recognises #!
$verbose = 1;     # Verbose by default

# Construct list of directories to search.
@absdirs = reverse grep(m!^/!, split(/:/, $ENV{'PATH'}, 999));

# Process command line arguments
if ($ARGV[0] eq '-s')
{
    shift;
    $verbose = 0;
}
die "Usage: $0 [-s] [file ...]\n" unless @ARGV || !-t;

@ARGV = '-' unless @ARGV;

# Process each file.
FILE: foreach $filename (@ARGV)
{
    open(IN, $filename) || ((warn "Can't process $filename: $!\n"), next);
    $_ = <IN>;
    next FILE unless /^#!/;  # Not a hash/bang file

    chop($cmd = $_);
    $cmd =~ s/^#! *//;
    ($cmd, $arg) = split(' ', $cmd, 2);
    $cmd =~ s!^.*/!!;

    # Now look (in reverse) for interpreter in absolute path
    $found = '';
    foreach $dir (@absdirs)
    {
     if (-x "$dir/$cmd")
     {
      warn "Ignoring $found\n" if $verbose && $found;
      $found = "$dir/$cmd";
     }
    }

    # Figure out how to invoke interpreter on this machine
    if ($found)
    {
     warn "Changing $filename to $found\n" if $verbose;
     if ($does_hashbang)
     {
      $_ = "#!$found";
      $_ .= ' ' . $arg if $arg ne '';
      $_ .= "\n";
     }
     else
     {
      $_ = <<EOF;
:
eval 'exec $found $arg -S \$0 \${1+"\$@"}'
    if \$running_under_some_shell;
EOF
     }
    }
    else
    {
     warn "Can't find $cmd in PATH, $filename unchanged\n" if $verbose;
     next FILE;
    }

    # Make new file if necessary
    if ($filename eq '-') { select(STDOUT); }
    else
    {
     rename($filename, "$filename.bak") ||
      ((warn "Can't modify $filename"), next FILE);
     open(OUT, ">$filename") ||
      die "Can't create new $filename: $!\n";
     ($def, $ino, $mode) = stat IN;
     $mode = 0755 unless $dev;
     chmod $mode, $filename;
     select(OUT);
    }

    # Print the new #! line (or the equivalent) and copy the rest of the file.
    print;
    while (<IN>)
    {
     print;
    }
    close IN;
    close OUT;
}

The code is derived from a script of the same name in the original Camel Book ('Programming Perl', first edition). This copy has been hacked a bit since then - and should be hacked some more. But I use it routinely -- indeed, I just copied it from one Mac to another, and since I've not installed Perl 5.10.0 on the second, I ran:

$ perl fixin fixin
Changing fixin to /usr/bin/perl
$

Thereby changing from the private install Perl to the standard one.

Exercise for the reader - rewrite the script in Python.

Jonathan Leffler