26

I have the following line of code that keeps giving me an error that Engine object has no object execute. I think I have everything right but no idea what keeps happening. It seemed others had this issue and restarting their notebooks worked. I'm using Pycharm and have restarted that without any resolution. Any help is greatly appreciated!

import pandas as pd
from sqlalchemy import create_engine, text
import sqlalchemy
import pymysql


masterlist = pd.read_excel('Masterlist.xlsx')

user = 'root'
pw = 'test!*'
db = 'hcftest'

engine = create_engine("mysql+pymysql://{user}:{pw}@localhost:3306/{db}"
                           .format(user=user, pw=pw, db=db))


results = engine.execute(text("SELECT * FROM companyname;"))

for row in results:
    print(row)
3
  • 1
    You need engine.connect(). It's lazy and won't actually connect until needed Commented Feb 1, 2023 at 22:16
  • with engine.connect() as conn: Commented Feb 1, 2023 at 22:17
  • Side note if you want a pretty good Python-based GUI driven MySQL Editor, Oracle created one that is FREE called MySQL Workbench, and it makes db work as easy as playing with Excel. Unless you are just doing a proof in concept, you might want to look into it and save youself a ton of time. Commented Feb 1, 2023 at 22:19

3 Answers 3

54

There was a change from 1.4 to 2.0. The above code will run fine with sqlalchemy version 1.4 I believe. setting SQLALCHEMY_WARN_20=1 python and running the above code reveals this warning:

<stdin>:1: RemovedIn20Warning: The Engine.execute() method is considered legacy as of the 1.x series of SQLAlchemy and will be removed in 2.0. All statement execution in SQLAlchemy 2.0 is performed by the Connection.execute() method of Connection, or in the ORM by the Session.execute() method of Session. (Background on SQLAlchemy 2.0 at: https://sqlalche.me/e/b8d9)

So the correct way to do the code now is:

with engine.connect() as conn:
    result = conn.execute(stmt)

source here describing the behavior in 1.4 and here describing the behavior in 2.0

Sign up to request clarification or add additional context in comments.

2 Comments

Did they make it harder to query dynamically on purpose?
@Frank You can find their """apology""" for the breakage here; scroll down to "explicit transactions" around PEP249. docs.sqlalchemy.org/en/14/changelog/… "SQLAlchemy 2.0 will do away with all attempts to implicitly commit transactions, and usage patterns will always require that the user demarcate the “beginning” and the “end” of a transaction in some way, in the same way as reading or writing to a file in Python has a “beginning” and an “end"
15
sql = f"""INSERT INTO user_apis
  (api_id, user_id, monthly_requests, total_requests)
  VALUES (1, {current_user.id}, 0, 0)"""

1.x

result = db.engine.execute(sql)

2.x

from sqlalchemy import text
with db.engine.begin() as conn:
    result = conn.execute(text(sql)) 
    conn.commit()              #2.x execute now only works with SELECT.
                               #Inserts, Updates and Deletes now must be 
                               #in a transaction and explicitly committed
                               #use engine echo=True to show transaction status

SELECT sql

with db.engine.connect() as conn:
    result = conn.execute(text(sql)).fetchall()

Add this method to do the right thing on both versions.

Then change all your db.engine.execute(sql) to myengine_execute(sql)

def myengine_execute(sql): 
  #If sqlalchemy version starts with 1.4 then do it the old way
  sqlalchemy_version = version("sqlalchemy")
  if sqlalchemy_version.startswith('1.4.'):
    with engine.connect() as conn: 
        return conn.execute(text(sql)) 
  else:
    #otherwise do it the new way with transactions:
    with engine.connect() as conn: 
        result = conn.execute(text(sql)) 
        #print(result.inserted_primary_key()) 
        conn.commit()

upd_sql = "update bankaccount set amount = amount+5e10 where id = 1234567" 
result = myengine_execute(upd_sql) 

Comments

1
from .. import db

def get():

    sql_statement = \
        """
            SELECT *
        """

    with db.engine.begin() as conn:
        response = conn.exec_driver_sql(sql_statement).all()
    
    return response

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.