Python Sybase slow compared to Perl?

Chuck May cmay4 at yahoo.com
Fri Sep 20 16:30:18 EDT 2002


I have always written my database scripts in Perl.  I am very interested 
in Python, and would like to start using it for all my scripting.  I am 
not trying to start a flame war, I'd just like to understand why a 
particular script I wrote runs so much faster under Perl.    The script in 
question takes roughly 3 times as long to run under Python.  It is very 
possible that there is a faster way to do this under Python.

I cut out most of the script, leaving only the part of the scrit that does 
all the work.  I am basically selecting all the fields from a table, 
looping over the results, and outputting the results in a fixed-width text 
file.  Seems simple enough.  

Here is the Perl code snippet:

   # output the actual data
   $sth = $dbh->prepare( "SELECT $select FROM $table->[0]" );
   $sth->execute();
   $num_recs = 0;
   $tempfile = "$dumpfile.tmp.gz";
   unlink $tempfile;
   open( DUMP_FILE, "| gzip -c > $tempfile" )
   while ( @data = $sth->fetchrow_array() ) {
       $line = "";
       for ( $i = 0; $i < scalar @lengths; $i++ ) {
           $line .= pack( "A$lengths[$i]", $data[$i] );
       }
       print DUMP_FILE "$line\n";
       $num_recs++;
   }
   close DUMP_FILE;
   $sth->finish();

and here is the Python code snippet:

   # output the actual data
   c = db.cursor()
   c.execute( "SELECT %s FROM %s" % ( select, table ) )
   num_recs = 0
   if os.path.isfile( "%s.gz" % dumpfile ):
       os.remove( "%s.gz" % dumpfile )
   file = os.popen( "gzip -c > %s.gz" % dumpfile, "w" )
   while 1:
       row = c.fetchone()
       if not row : break
    
       line = []
       for i in range( len( row ) ):
           line.append( "%-*s" % ( lengths[i], row[i] ) )

       print >> file, "".join( line )
       num_recs += 1

   file.close()
   c.close()

No matter what table how many records there are, the Python script always 
takes longer to run (usually by a facter of 3 or more).  

I am still a Python newbie, so I may be doing something wrong.  Has anyone 
else experienced similar results?  Is this due to a poorly optimized 
Sybase module?  I really want to use Python, and I don't mind giving up a 
little speed, but this is more than I can accept.

I ran the Python script using the profiler and the output is below.  Any 
help would be much appreciated.  Thanks.

Chuck May
IMS, Inc.

-------------

profile output:

 Ordered by: standard name

 ncalls  tottime  percall  cumtime  percall filename:lineno(function)
      1    0.000    0.000 1230.540 1230.540 <string>:1(?)
      4    0.000    0.000    0.000    0.000 Sybase.py:114(_get_diag)
      2    0.000    0.000    0.000    0.000 Sybase.py:141(_ct_errors)
      3    0.000    0.000    0.000    0.000 Sybase.py:148(_row_bind)
 900345   96.240    0.000   96.240    0.000 Sybase.py:166(_extract_row)
 900348  177.670    0.000  273.910    0.000 Sybase.py:180(_fetch_rows)
      3    0.000    0.000    0.010    0.003 Sybase.py:229(__init__)
      3    0.000    0.000    0.000    0.000 Sybase.py:246(__del__)
 900361   83.230    0.000  267.090    0.000 Sybase.py:258(_lock)
 900361   86.720    0.000  269.000    0.000 Sybase.py:262(_unlock)
      3    0.000    0.000    0.010    0.003 Sybase.py:312(close)
      3    0.000    0.000    0.000    0.000 Sybase.py:328(execute)
 900348  178.280    0.000  988.260    0.001 Sybase.py:365(fetchone)
      1    0.000    0.000    0.000    0.000 Sybase.py:408(fetchall)
      3    0.000    0.000    0.000    0.000 Sybase.py:451(_fetch_rowcount)
      3    0.000    0.000    0.000    0.000 Sybase.py:466(_start_results)
      2    0.000    0.000    0.010    0.005 Sybase.py:494(__init__)
      2    0.000    0.000    0.000    0.000 Sybase.py:522(_raise_error)
      2    0.010    0.005    0.010    0.005 Sybase.py:527(connect)
      2    0.000    0.000    0.000    0.000 Sybase.py:564(__del__)
      4    0.000    0.000    0.000    0.000 Sybase.py:570(close)
      3    0.000    0.000    0.010    0.003 Sybase.py:613(cursor)
      2    0.000    0.000    0.000    0.000 Sybase.py:618(execute)
      2    0.000    0.000    0.000    0.000 Sybase.py:640(_fetch_results)
      2    0.000    0.000    0.010    0.005 Sybase.py:667(connect)
      1    0.000    0.000 1230.540 1230.540 bsi_dump.py:176(main)
      3    0.000    0.000    0.000    0.000 bsi_dump.py:238(outputMessage)
      1  242.210  242.210 1230.520 1230.520 bsi_dump.py:39(dumptable)
      1    0.030    0.030    0.030    0.030 commands.py:50
(getstatusoutput)
      1    0.000    0.000    0.000    0.000 getopt.py:121(do_shorts)
      1    0.000    0.000    0.000    0.000 getopt.py:136(short_has_arg)
      1    0.000    0.000    0.000    0.000 getopt.py:35(getopt)
      1    0.010    0.010    0.010    0.010 getpass.py:18(unix_getpass)
      1    0.000    0.000    0.000    0.000 getpass.py:71(_raw_input)
      2    0.000    0.000    0.000    0.000 posixpath.py:194(isfile)
      1    0.080    0.080 1230.620 1230.620 profile:0(main())
      0    0.000             0.000          profile:0(profiler)
      2    0.000    0.000    0.000    0.000 stat.py:29(S_IFMT)
      2    0.000    0.000    0.000    0.000 stat.py:54(S_ISREG)
      2    0.000    0.000    0.000    0.000 string.py:121(join)
      2    0.000    0.000    0.000    0.000 threading.py:39(__init__)
1800738   60.630    0.000   60.630    0.000 threading.py:44(_note)
1800738   60.440    0.000   60.440    0.000 threading.py:581
(currentThread)
      2    0.000    0.000    0.000    0.000 threading.py:64(RLock)
      2    0.000    0.000    0.000    0.000 threading.py:69(__init__)
 900369  123.010    0.000  183.860    0.000 threading.py:81(acquire)
 900369  122.060    0.000  182.280    0.000 threading.py:99(release)




More information about the Python-list mailing list