Обсуждение: BUG #5232: plpythonu s=s.op() raises an exception
The following bug has been logged online: Bug reference: 5232 Logged by: David Gardner Email address: dgardner@creatureshop.com PostgreSQL version: 8.4.1 Operating system: Debian, amd64 Description: plpythonu s=s.op() raises an exception Details: If I create the following: CREATE OR REPLACE FUNCTION pyreplace(src text,s text) RETURNS text AS $BODY$ try: src=src.replace(s,'') return src except Exception,e: return str(e) $BODY$ LANGUAGE 'plpythonu' VOLATILE COST 100; ALTER FUNCTION pyreplace(src text,s text) OWNER TO dgardner; Then: SELECT * FROM pyreplace('this is a very long string','is'); pyreplace --------------------------------------------------- local variable 'src' referenced before assignment (1 row) However in python I can do: def pyreplace(src,s): try: src=src.replace(s,'') return src except Exception,e: return str(e) pyreplace('this is a very long string','is') ----- produces: 'th a very long string'
"David Gardner" <dgardner@creatureshop.com> writes: > CREATE OR REPLACE FUNCTION pyreplace(src text,s text) > RETURNS text AS > $BODY$ > try: > src=src.replace(s,'') > return src > except Exception,e: > return str(e) > $BODY$ > LANGUAGE 'plpythonu' VOLATILE > COST 100; Weird. You seem to need both the try block and the overwrite of the parameter to make it misbehave. I suspect this means we're doing something a bit wrong in setting up the python variable for the parameter. Unfortunately I don't know enough about python to go further than that. regards, tom lane
Not sure about the try block being related, I included it in my example mostly because the example is a simplified version of some code I was working on that had a try/except block. I tried the function without the try block and it raised the same exception (just uncaught): CREATE OR REPLACE FUNCTION pyreplacenotry(src text, s text) RETURNS text AS $BODY$ src=src.replace(s,'') return src $BODY$ LANGUAGE 'plpythonu' VOLATILE COST 100; ALTER FUNCTION pyreplacenotry(text, text) OWNER TO dgardner; gives me: ERROR: PL/Python: PL/Python function "pyreplacenotry" failed DETAIL: <type 'exceptions.UnboundLocalError'>: local variable 'src' referenced before assignment ********** Error ********** ERROR: PL/Python: PL/Python function "pyreplacenotry" failed SQL state: XX000 Detail: <type 'exceptions.UnboundLocalError'>: local variable 'src' referenced before assignment However this works: CREATE OR REPLACE FUNCTION pyreplacenoreassign(src text, s text) RETURNS text AS $BODY$ return src.replace(s,'') $BODY$ LANGUAGE 'plpythonu' VOLATILE COST 100; ALTER FUNCTION pyreplacenoreassign(text, text) OWNER TO dgardner; Tom Lane wrote: > "David Gardner" <dgardner@creatureshop.com> writes: > >> CREATE OR REPLACE FUNCTION pyreplace(src text,s text) >> RETURNS text AS >> $BODY$ >> try: >> src=src.replace(s,'') >> return src >> except Exception,e: >> return str(e) >> $BODY$ >> LANGUAGE 'plpythonu' VOLATILE >> COST 100; >> > > Weird. You seem to need both the try block and the overwrite of the > parameter to make it misbehave. I suspect this means we're doing > something a bit wrong in setting up the python variable for the > parameter. Unfortunately I don't know enough about python to go further > than that. > > regards, tom lane > > -- David Gardner Pipeline Tools Programmer Jim Henson Creature Shop dgardner@creatureshop.com
On tor, 2009-12-03 at 14:46 -0800, David Gardner wrote: > Not sure about the try block being related, I included it in my > example mostly because the example is a simplified version of some > code I was working on that had a try/except block. > I tried the function without the try block and it raised the same > exception (just uncaught): > > CREATE OR REPLACE FUNCTION pyreplacenotry(src text, s text) > RETURNS text AS > $BODY$ > src=src.replace(s,'') > return src > $BODY$ > LANGUAGE 'plpythonu' VOLATILE > COST 100; > ALTER FUNCTION pyreplacenotry(text, text) OWNER TO dgardner; > > gives me: > ERROR: PL/Python: PL/Python function "pyreplacenotry" failed > DETAIL: <type 'exceptions.UnboundLocalError'>: local variable 'src' > referenced before assignment What is going on internally is something like this: src = 'xyz' def pyreplacenotry(): src=src.replace('x', 'y') return src pyreplacenotry() which fails with that same error. So you should not try to assign to the parameters of a function.
Peter Eisentraut <peter_e@gmx.net> writes: > ... So you should not try to assign to > the parameters of a function. If it's allowed in normal Python functions, that definitely needs to be documented. Better would be to fix it or at least throw a more intelligible error ... regards, tom lane
On tor, 2009-12-03 at 19:02 -0500, Tom Lane wrote: > Peter Eisentraut <peter_e@gmx.net> writes: > > ... So you should not try to assign to > > the parameters of a function. > > If it's allowed in normal Python functions, that definitely needs to be > documented. Better would be to fix it or at least throw a more > intelligible error ... I have added documentation for it.