Python & Neo4j: Check for empty statementresult - python

I am using a python script to do a cypher statement that should return 0..n results. I use a foreach loop to get all values:
for column1 in results['col1']:
# do some stuff
If the Statementresult is empty, the loop will not be executed - of course. I want to check the Statementresult before. If there is no result the python script shall do something different, e. g. printing a message.
I tried to compare the statementresult with None (but its an object, even if its empty), or use the first index. I looked for a solution in the documentation and online but could not find anything. How can I check if its empty or not? Is it also possible to get e. g. the 3rd result if it exists?
Thanks!
Stefan

I found a way using the internal method peek() of class StatementResult. If you call this method it will raise an error in case there no records in the result object. I wrapped this code within a function which can be used passing the Result object to it.
def isResultRecord(results):
try:
results.peek()
except ResultError:
return False
else:
return True

if (results.peek() is None):
# empty object

Related

How can I use Python's exec() and eval() to execute arbitrary code AND return a value afterwards?

I'm looking for a function that will let me execute code passed as a string, but also return a value upon completion. I have found Python's exec and eval, each of which manage to do a part of what I want:
exec lets me execute some lines of code which I pass as a string: print to the console; set or change variables; write to files etc.
eval lets me evaluate a single expression and returns the value of this expression.
However, the functionality I want is to combine these: with a single function call, I want to execute some arbitrary code, and then return a value, which might be dependent on the code executed.
To contextualise, I want to modify the in-built Pickle __reduce__ method so that I can execute some code in the background while the object un-pickles. However, at the end of that code execution, I still want to return the original object that was pickled.
Pickle's __reduce__ has to return a function which is used to reassemble the object on un-pickling, so I want a use of eval and exec that lets me combine their usage into a single function call.
As an example, my code might look something like this:
def __reduce__(self):
code = """with open("flag.txt", "w") as f:\n\tf.write("A flag I have left!")\ndict()"""
return exec, (code, ), None, None, iter(self.items())
The odd return formatting is a quirk of Pickle. The oddly formatted code string should do this:
with open("flag.txt", "w") as f:
f.write("A flag I have left")
dict() # I'm trying to get the intepreter to 'evaluate' this final line
However, this doesn't work, as exec just does nothing with this final line, and returns None. If I swap, and use eval instead, then I get an error too, as eval can't do anything with the lines above.
I ave tried using the in-built compile method, but this doesn't actually seem to help because eval still won't evaluate compiled execution code.
I also see that this problem has popped up elsewhere on SO (here and here) but I'm unsatisfied with the answers provided, because they involve defining new functions, which are then useless in the context of getting Pickle to execute them on un-pickling, where the interpreter is naive of their definition.
Is there any way to neatly combine these expressions to achieve arbitrary execution as well as returning a value?
The best solution I could find to this problem is one based on some code from Yannic Kilcher.
You can combine the functions like this:
eval("exec(exec_code) or to_return")
eval will always try to return the value of the expression you have passed. If you pass a conditional expression, like the one above, then it will try and evaluate each part in turn to find the value of the whole conditional. As such, it will run your exec code, achieving what you need there, and then, finding that it evaluates to None, will return whatever the value of to_return is, because of the or. Therefore, if you make to_return your dictionary object constructor, then your code will run the exec statement first upon un-pickling, and then return a dictionary object as intended.

Updating only the first occurrence of an object in a queue with python without break

I created a function in python that will change the priority for the first occurrence of an object, but im having trouble fixing it so that it would only work for the first occurrence without the use of break. In my code below I have used break and it works as intended but I would like to not use it.
def update_priority(self, object, priority):
for i in range(len(self._queue)):
if object == self._queue[i].get_item():
# checking object already has that priority
if priority == self._queue[i].get_priority():
# dont change if it has the priority
pass
# if the object does not have that priority set to new
else:
self._queue[i].set_priority(pri)
break
else:
pass
It sounds like you also want to learn how to reduce the length of the code. A rule of thumb is to concentrate on making your code clear and concise first, so you can try to identify ways to simplify the structure. For example, you can restructure and remove redundant branches. Many of your cases are just passes. Also, yes, college classes say that break statements aren't great. For clarity, you might want to use a conditional variable to end the loop. In this case, you don't really need to do that, but an alternative is to wrap the code in a function and bypass the rest of a loop simply by returning, You already use a function, so you can just return from the function if all you do is update the one item's priority (and exit). Perhaps you want to return a status code indicating that an item was found or not. (True or False).
def update_priority(self, object, priority):
# check all items in the queue (you do not require the index.)
# the entry is stored in "entry"
for entry in self._queue:
# if you find the object and its priority needs an update
if object == entry.get_item() and priority != entry.get_priority():
# set the priority
entry.set_priority(priority)
# return true for success, you found the object and updated it
return True
""" If you arrive at this line, the object didn't exist or
it didn't need an update (if you need to distinguish between "object not found" and
"object found but didn't update," use an extra flag or nest the != entry.get_priority as you did before"""
return False
Your solution is correct you do not need to change it so it doesnt use break. There is no other way to end a loop unless its a while loop and the condition is false or you reach the end of range in a for loop.

How to avoid for-in looping over None in Python

I know I can add some if blocks around to avoid this problem, but I am looking for a best practice or good/nice way to handle this kind of programming problem.
I am looping through the result of a function, without storing the result first in a separate variable; something like this:
for item in mycustimitemgetter.itter():
dosomething()
The itter function is returning None instead of an empty list [], and Python throws an exception per None. This is correct python behavior and nothing's wrong with it. But I'm looking for a best practice solution to:
a) keep the code clean and simple (not storing the result in a var and do if != None, etc..)
b) treat a None return value like an empty list i.e. do not run the loop and silently ignore the fact that function returned a None value.
Perhaps, use the fact that both [] and None evaluate as False, but lists with contents don't:
for item in (mycustimitemgetter.itter() or []):
dosomething()
You have a method called itter() which returns an iterable object. I would say that given the name of the function, it's reasonable to say "the returned value should always be iterable". So, if you're returning a list, you should return an empty list if you have no values.
Code there to be executed. There is nothing wrong with adding:
if retval is None:
return []
return retval
or
return retval or []
to the end of your itter() implementation, depending on the types in use.
Consider this: you wrote the code and you're facing this problem. What about someone else who's trying to use your code without knowing what you know. What do they expect?
Alternatively you should use Generators (if suitable). They contain a 'next' method (see the docs at the link), which you can return false if there are no values.

Understanding the result after using Python's clear() method

I don't understand the result of the code below. Why is the result None?
m = {(1,2):1.0, (5,4):0.5, (3,4):0.75}
print(m.clear())
result: **None**
But if I write as
m.clear()
print(m)
result : **{}**
I have other result.
print(m.clear()) prints the value returned by the call m.clear(). print m prints the object m; clearly two very different things, and so it's unsurprising that they produce different output.
The documentation for dictionary types simply says of clear:
Remove all items from the dictionary.
That's what it does. It's not documented as returning anything, while all the documentation for all the methods that do return something are explicit about what they return (usually methods that alter a collection only return None). So there's no reason to expect it to return anything.
You are printing the return value of m.clear(), which returns None. It returns None because the .clear() method clears the dictionary in place.
By convention, any method on a default Python type that alters the mutable structure in-place, returns None. The same applies to list.sort() or to set.add(), for example.
Your second sample does not print the return value of m.clear(). It prints the empty dictionary after you cleared it.

Executing code in a python module as soon as it is included

I am attempting to use a module called interface.py which defines a list of conditions and a few functions to check arguments against those conditions. There are many thousands of conditions however, and so I want to use a dictionary instead of a list to prevent needing to look at all of them. To do this I'm using the following code:
def listToDictionary(list):
"""This function takes a list of conditions and converts it to a dictionary
that uses the name of the condition as a key."""
d = {}
for condition in list:
if condition.name.lower() not in d:
d[condition.name.lower()] = []
d[condition.name.lower()].append(condition)
return d
conditionList = listToDictionary(conditions.list) #the condition list comes from another module
Further into the file are the actual interface functions that take arguments to compare with the list of conditions - these functions are written assuming that conditionList will be a dictionary.
Unfortunately this isn't working. Giving error details is difficult because this code is being imported by a django page and I am trying to avoid talking about django so this question stays uncomplicated. Essentially the pages including this code will not load, and if I change it back to just using a list everything works fine.
My suspicion is that the problem has to do with how Python treats import statements. I need the listToDictionary conversion to run as soon as interface.py is imported, otherwise the interface functions will expect a dictionary and get a list instead. Is there any way to ensure that this is happening?
An educated guess: the list in conditions.list is not yet fully constructed when your module is being imported. As a result, you get a dictionary that is missing some entries or even empty, which is causing problems later. Try deferring the construction of the dict, like this:
conditionTable = None # shouldn't call it list if it's a dict
def get_cond_table():
global conditionTable
if conditionTable is None:
conditionTable = listToDictionary(conditions.list)
return conditionTable
Instead of referring to conditionList in your functions, refer to get_cond_table().
Alright, I found out that the problem was in another function that was still expecting the dictionary to be a list. The reason I couldn't see it right away is that Django left a very cryptic error message. I was able to get a better one using python manage.py shell and importing the module manually.
Thanks for your help everyone.

Categories