Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Friday, July 25, 2014 9:28:32 PM UTC-4, Steven D'Aprano wrote: On Fri, 25 Jul 2014 17:06:17 -0700, Bruce Whealton wrote: Steven, See below please. The explanation did help. OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): In Python 2, you could include parenthesised parameters inside function declarations as above. That is effectively a short cut for this version, where you collect a single argument and then expand it into three variables: def add(self, sub_pred_obj): sub, pred, obj = sub_pred_obj I setup Eclipse to use python 2.7.x and tried to run this and it just gave an error on line 9 where the def add function is declared. It just says invalid syntax and points at the parentheses that are in the function definition def add(self, (subj, pred, obj)): So, from what you said, and others, it seems like this should have worked but eclipse would not run it. I could try to load it into IDLE. In Python 3, that functionality was dropped and is no longer allowed. Now you have to use the longer form. I'm not sure I follow what the longer method is. Can you explain that more, please. [...] There are other places where I thought that there were too many parentheses and I tried removing one set of them. For example this snippet here: def remove(self, (sub, pred, obj)): Remove a triple pattern from the graph. triples = list(self.triples((sub, pred, obj))) Firstly, the remove method expects to take a *single* argument (remember that self is automatically provided by Python) which is then automatically expanded into three variables sub, pred, obj. So you have to call it with a list or tuple of three items (or even a string of length exactly 3). Then, having split this list or tuple into three items, it then joins them back again into a tuple: (sub, pred, obj) passes that tuple to the triples method: self.triples((sub, pred, obj)) (not shown, but presumably it uses the same parenthesised parameter trick), and then converts whatever triples returns into a list: The full code listing should be available in the code paste link that I included. list(self.triples((sub, pred, obj))) that list then being bound to the name triples. Thanks, the explanation helped, Bruce -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Friday, July 25, 2014 11:25:15 PM UTC-4, Chris Angelico wrote: On Sat, Jul 26, 2014 at 10:06 AM, Bruce Whealton Chris, In response to your comments below, I'm comfortable changing this to use python 3. As others have said, this is something that changed in Python 3. So you have two parts to the problem: firstly, your code is bound to Python 2 by a triviality, and secondly, Eclipse is complaining about it. But a better solution, IMO, would be to avoid that implicit tuple unpacking. It's not a particularly clear feature, and I'm not sorry it's gone from Py3. The simplest way to change it is to just move it into the body: OK, that makes sense. So, I cut out the Alternatively... suggestion you made. def add(self, args): sub, pred, obj = args # rest of code as before Preferably with a better name than 'args'. Yes, I could call it triples. triples = list(self.triples((sub, pred, obj))) Are the two sets parentheses needed after self.triples? That syntax is confusing to me. It seems that it should be triples = list(self.triples(sub, pred, obj)) No, that's correct. The extra parens force that triple to be a single tuple of three items, rather than three separate arguments. Here's a simpler example: lst = [] lst.append(1,2,3) Traceback (most recent call last): File pyshell#25, line 1, in module lst.append(1,2,3) TypeError: append() takes exactly one argument (3 given) lst.append((1,2,3)) addme = 4,5,6 lst.append(addme) lst [(1, 2, 3), (4, 5, 6)] This is helpful and makes sense... clarifies it for me. The list append method wants one argument, and appends that argument to the list. Syntactically, the comma has multiple meanings; when I assign 4,5,6 to a single name, it makes a tuple, but in a function call, it separates args in the list. I don't see why the triples() function should be given a single argument, though; all it does is immediately unpack it. It'd be better to just remove the parens and have separate args: triples = list(self.triples(sub, pred, obj)) I didn't see the above in the code... Is this something I would need to add and if so, where? def triples(self, sub, pred, obj): While I'm looking at the code, a few other comments. I don't know how much of this is your code and how much came straight from the book, but either way, don't take this as criticism, but just as suggestions for ways to get more out of Python. So far it is just from the book, and just serves as an example... It is also a few years old, having been published in 2009. Inside remove(), you call a generator (triples() uses yield to return multiple values), then construct a list, and then iterate exactly once over that list. Much more efficient and clean to iterate directly over what triples() returns, as in save(); that's what generators are good for. In triples(), the code is deeply nested and repetitive. I don't know if there's a way to truly solve that, but I would be inclined to flatten it out a bit; maybe check for just one presence, to pick your index, and then merge some of the code that iterates over an index. Not sure though. I would have to get a better understanding of this. (Also: It's conventional to use is not None rather than != None to test for singletons. It's possible for something to be equal to None without actually being None.) I would recommend moving to Python 3, if you can. Among other benefits, the Py3 csv module allows you to open a text file rather than opening a binary file and manually encoding/decoding all the parts separately. Alternatively, if you don't need this to be saving and loading another program's files, you could simply use a different file format, which would remove the restrictions (and messes) of the CSV structure. I was curious about why the binary flag was being used. It just made no sense to me. Instead of explicitly putting f.close() at the end of your load and save methods, check out the 'with' statement. It'll guarantee that the file's closed even if you leave early, get an exception, or anything like that. Also, I'd tend to use the .decode() and .encode() methods, rather than the constructors. So here's how I'd write a Py2 load: I would like to see this in python 3 format. def load(self, filename): with open(filename, rb) as f: for sub, pred, obj in csv.reader(f): self.add((sub.decode(UTF-8), pred.decode(UTF-8), obj.decode(UTF-8))) (You might want to break that back out into three more lines, but this parallels save(). If you break this one, you probably want to break save() too.) Hope that helps! ChrisA Thanks, Bruce -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Mon, 28 Jul 2014 03:39:48 -0700, Bruce Whealton wrote: I setup Eclipse to use python 2.7.x and tried to run this and it just gave an error on line 9 where the def add function is declared. First step is to confirm that Eclipse actually is using Python 2.7. Can you get it to run this code instead? Put this in a module, and then run it: import sys print(sys.version) Once you have confirmed that Eclipse really is running 2.7, next is to confirm what the syntax error actually is. Carefully check the source code that there are no missing close-parentheses just before the def add method. (Sometimes, a missing parenthesis won't show up as a Syntax Error until *after* the actual error.) It may be helpful to see the exact syntax error. If possible, cut and paste (don't retype!) the full error message. It should look something like this: py def add(a, (b, c)): File stdin, line 1 def add(a, (b, c)): ^ SyntaxError: invalid syntax Notice that the caret ^ points to where Python discovers the error. If you confirm that Eclipse is using Python 2.7, but it still complains about the parenthesis, my guess -- and it's only a guess -- is that somehow you have an invisible or non-printing character inserted into the file at that position, and that's causing the Python parser to choke. I can demonstrate a working example indirectly, with the exec function: py exec(def x(a,(b,c)): pass) # Works fine. py x function x at 0xb7e71a74 Now here it is again, but with an invisible control character inserted: py exec(def x(a,\a(b,c)): pass) Traceback (most recent call last): File stdin, line 1, in module File string, line 1 def x(a,(b,c)): pass ^ SyntaxError: invalid syntax Notice that when Python prints the error, the \a control character doesn't show up. It's there, but you can't see it. It just says invalid syntax and points at the parentheses that are in the function definition def add(self, (subj, pred, obj)): So, from what you said, and others, it seems like this should have worked but eclipse would not run it. I could try to load it into IDLE. Whenever you have trouble with one IDE, it's good to get a second opinion in another IDE. They might both be buggy, but they're unlikely to both have the same bug. Also, try to run the file directly from the shell, without an IDE. from the system shell (cmd.exe if using Windows, bash or equivalent for Linux), run: python27 /path/to/yourfile.py You'll obviously need to adjust the pathname, possibly even give the full path to the Python executable. [...] In Python 3, that functionality was dropped and is no longer allowed. Now you have to use the longer form. I'm not sure I follow what the longer method is. Can you explain that more, please. I referred to the parenthesised parameter version as a short cut for a method that takes a single argument, then manually expands that argument into three items. Let me show them together to make it more obvious: # Unparenthesised version, with manual step. def add(self, sub_pred_obj): sub, pred, obj = sub_pred_obj do_stuff_with(sub or pred or obj) # Parenthesised shortcut. def add(self, (sub, pred, obj)): do_stuff_with(sub or pred or obj) Both methods take a single argument, which must be a sequence of exactly three values. The second version saves a single line, hence the first version is longer :-) -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Monday, July 28, 2014 11:28:40 AM UTC-4, Steven D'Aprano wrote: On Mon, 28 Jul 2014 03:39:48 -0700, Bruce Whealton wrote: Stephen, I went to my Ubuntu box inside vmware and added a #!/usr/bin/env python2.7 to the top. Then I made the file executable and it ran the code perfectly. First step is to confirm that Eclipse actually is using Python 2.7. Can you get it to run this code instead? Put this in a module, and then run it: import sys print(sys.version) I had both python2.7 and python3.4. I could be less specific with my shebang line but what the heck. I then installed pydev into my eclipse environment within the Ubuntu virtual machine and it ran the program just fine. So, I suspect the extra character was only an issue on Windows. I thought I had it setup to show even hidden characters. Anyway, thanks so much for all the help...everyone. It might be interesting for me to convert this to a module that runs with python 3. Bruce It just says invalid syntax and points at the parentheses that are in the function definition def add(self, (subj, pred, obj)): So, from what you said, and others, it seems like this should have worked but eclipse would not run it. I could try to load it into IDLE. Whenever you have trouble with one IDE, it's good to get a second opinion in another IDE. They might both be buggy, but they're unlikely to both have the same bug. Also, try to run the file directly from the shell, without an IDE. from the system shell (cmd.exe if using Windows, bash or equivalent for Linux), run: python27 /path/to/yourfile.py You'll obviously need to adjust the pathname, possibly even give the full path to the Python executable. [...] In Python 3, that functionality was dropped and is no longer allowed. Now you have to use the longer form. I'm not sure I follow what the longer method is. Can you explain that more, please. I referred to the parenthesised parameter version as a short cut for a method that takes a single argument, then manually expands that argument into three items. Let me show them together to make it more obvious: # Unparenthesised version, with manual step. def add(self, sub_pred_obj): sub, pred, obj = sub_pred_obj do_stuff_with(sub or pred or obj) # Parenthesised shortcut. def add(self, (sub, pred, obj)): do_stuff_with(sub or pred or obj) Both methods take a single argument, which must be a sequence of exactly three values. The second version saves a single line, hence the first version is longer :-) -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On 7/25/2014 8:06 PM, Bruce Whealton wrote: The book has python 2.x code. If the modules in the book use the Natural Language Toolkit (nltk), then I believe you are currently stuck with using 2.7. If it does not, and you want to run with 3.3 or 3.4, then use 2to3 to do most to all of the conversion for you. C:\Programs\Python34python Tools/scripts/2to3.py -h Usage: 2to3 [options] file|dir ... Options: -h, --helpshow this help message and exit -d, --doctests_only Fix up doctests only -f FIX, --fix=FIX Each FIX specifies a transformation; default: all -j PROCESSES, --processes=PROCESSES Run 2to3 concurrently -x NOFIX, --nofix=NOFIX Prevent a transformation from being run -l, --list-fixes List available transformations -p, --print-function Modify the grammar so that print() is a function -v, --verbose More verbose logging --no-diffsDon't show diffs of the refactoring -w, --write Write back modified files -n, --nobackups Don't write backups for modified files -o OUTPUT_DIR, --output-dir=OUTPUT_DIR Put output files in this directory instead of overwriting the input files. Requires -n. -W, --write-unchanged-files Also write files even if no changes were required (useful with --output-dir); implies -w. --add-suffix=ADD_SUFFIX Append this string to all output filenames. Requires -n if non-empty. ex: --add-suffix='3' will generate .py3 files. This is the user interface for lib2to3. -- Terry Jan Reedy -- https://mail.python.org/mailman/listinfo/python-list
Prob. Code Downloaded for Programming the Semantic Web (python code)
Hello all, I downloaded some code accompanying the book Programming the Semantic Web. This question is not Semantic Web related and I doubt that one needs to know anything about the Semantic Web to help me with this. It's the first code sample in the book, I'm embarrassed to say. I have the code shared here (just one file, not the majority of the book or anything): http://pastebin.com/e870vjYK OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): It complains about the parentheses just before sub. Simply removing them just moves me down to another error. I did try using python 3.x (3.4 to be specific), which meant changing print statements to function calls. Of course, that didn't fix the errors I was mentioning. The text uses python 2.7.x. There are other places where I thought that there were too many parentheses and I tried removing one set of them. For example this snippet here: def remove(self, (sub, pred, obj)): Remove a triple pattern from the graph. triples = list(self.triples((sub, pred, obj))) Are the two sets parentheses needed after self.triples? That syntax is confusing to me. It seems that it should be triples = list(self.triples(sub, pred, obj)) The full listing is here: http://pastebin.com/e870vjYK I agree with the authors that python is a fun and easy language to use, thus it is strange that I am getting stuck here. Thanks, Bruce -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): It complains about the parentheses just before sub. Seems like this code is Python 2.x. Skip -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Fri, Jul 25, 2014 at 5:21 PM, Skip Montanaro s...@pobox.com wrote: OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): It complains about the parentheses just before sub. Seems like this code is Python 2.x. For me, this code ran on all of 2.4, 2.5, 2.6 and 2.7, but not on any of 3.0, 3.1, 3.2, 3.3 or 3.4. HTH -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Jul 25, 2014 6:54 PM, Dan Stromberg drsali...@gmail.com wrote: On Fri, Jul 25, 2014 at 5:21 PM, Skip Montanaro s...@pobox.com wrote: OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): It complains about the parentheses just before sub. Seems like this code is Python 2.x. For me, this code ran on all of 2.4, 2.5, 2.6 and 2.7, but not on any of 3.0, 3.1, 3.2, 3.3 or 3.4. Python 3.x no longer allows tuple parameter unpacking in function signatures. See PEP 3113. -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Fri, 25 Jul 2014 17:06:17 -0700, Bruce Whealton wrote: OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): In Python 2, you could include parenthesised parameters inside function declarations as above. That is effectively a short cut for this version, where you collect a single argument and then expand it into three variables: def add(self, sub_pred_obj): sub, pred, obj = sub_pred_obj In Python 3, that functionality was dropped and is no longer allowed. Now you have to use the longer form. [...] There are other places where I thought that there were too many parentheses and I tried removing one set of them. For example this snippet here: def remove(self, (sub, pred, obj)): Remove a triple pattern from the graph. triples = list(self.triples((sub, pred, obj))) Firstly, the remove method expects to take a *single* argument (remember that self is automatically provided by Python) which is then automatically expanded into three variables sub, pred, obj. So you have to call it with a list or tuple of three items (or even a string of length exactly 3). Then, having split this list or tuple into three items, it then joins them back again into a tuple: (sub, pred, obj) passes that tuple to the triples method: self.triples((sub, pred, obj)) (not shown, but presumably it uses the same parenthesised parameter trick), and then converts whatever triples returns into a list: list(self.triples((sub, pred, obj))) that list then being bound to the name triples. Are the two sets parentheses needed after self.triples? That syntax is confusing to me. It seems that it should be triples = list(self.triples(sub, pred, obj)) It's needed because the triples method is written def triples(self, (sub, pred, obj)): instead of the more obvious: def triples(self, sub, pred, obj): -- Steven -- https://mail.python.org/mailman/listinfo/python-list
Re: Prob. Code Downloaded for Programming the Semantic Web (python code)
On Sat, Jul 26, 2014 at 10:06 AM, Bruce Whealton futurewavewebdevelopm...@gmail.com wrote: OK, Eclipse with PyDev doesn't like this first line, with the function: def add(self, (sub, pred, obj)): As others have said, this is something that changed in Python 3. So you have two parts to the problem: firstly, your code is bound to Python 2 by a triviality, and secondly, Eclipse is complaining about it. One solution would be to teach Eclipse that this is legal, or for you to just ignore its complaints. If your code works in Python 2.7, then there's no big problem. You could try telling Eclipse that you're using Python 2 (maybe by putting a shebang at the top of your script), but that may not work; in any case, that's just an issue with the editor. But a better solution, IMO, would be to avoid that implicit tuple unpacking. It's not a particularly clear feature, and I'm not sorry it's gone from Py3. The simplest way to change it is to just move it into the body: def add(self, args): sub, pred, obj = args # rest of code as before Preferably with a better name than 'args'. Alternatively, change the places that call add() and have them provide four separate arguments, in which case the signature would simply be: def add(self, sub, pred, obj): like you'd expect. triples = list(self.triples((sub, pred, obj))) Are the two sets parentheses needed after self.triples? That syntax is confusing to me. It seems that it should be triples = list(self.triples(sub, pred, obj)) No, that's correct. The extra parens force that triple to be a single tuple of three items, rather than three separate arguments. Here's a simpler example: lst = [] lst.append(1,2,3) Traceback (most recent call last): File pyshell#25, line 1, in module lst.append(1,2,3) TypeError: append() takes exactly one argument (3 given) lst.append((1,2,3)) addme = 4,5,6 lst.append(addme) lst [(1, 2, 3), (4, 5, 6)] The list append method wants one argument, and appends that argument to the list. Syntactically, the comma has multiple meanings; when I assign 4,5,6 to a single name, it makes a tuple, but in a function call, it separates args in the list. I don't see why the triples() function should be given a single argument, though; all it does is immediately unpack it. It'd be better to just remove the parens and have separate args: triples = list(self.triples(sub, pred, obj)) def triples(self, sub, pred, obj): While I'm looking at the code, a few other comments. I don't know how much of this is your code and how much came straight from the book, but either way, don't take this as criticism, but just as suggestions for ways to get more out of Python. Inside remove(), you call a generator (triples() uses yield to return multiple values), then construct a list, and then iterate exactly once over that list. Much more efficient and clean to iterate directly over what triples() returns, as in save(); that's what generators are good for. In triples(), the code is deeply nested and repetitive. I don't know if there's a way to truly solve that, but I would be inclined to flatten it out a bit; maybe check for just one presence, to pick your index, and then merge some of the code that iterates over an index. Not sure though. (Also: It's conventional to use is not None rather than != None to test for singletons. It's possible for something to be equal to None without actually being None.) I would recommend moving to Python 3, if you can. Among other benefits, the Py3 csv module allows you to open a text file rather than opening a binary file and manually encoding/decoding all the parts separately. Alternatively, if you don't need this to be saving and loading another program's files, you could simply use a different file format, which would remove the restrictions (and messes) of the CSV structure. Instead of explicitly putting f.close() at the end of your load and save methods, check out the 'with' statement. It'll guarantee that the file's closed even if you leave early, get an exception, or anything like that. Also, I'd tend to use the .decode() and .encode() methods, rather than the constructors. So here's how I'd write a Py2 load: def load(self, filename): with open(filename, rb) as f: for sub, pred, obj in csv.reader(f): self.add((sub.decode(UTF-8), pred.decode(UTF-8), obj.decode(UTF-8))) (You might want to break that back out into three more lines, but this parallels save(). If you break this one, you probably want to break save() too.) Hope that helps! ChrisA -- https://mail.python.org/mailman/listinfo/python-list