Re: Prob. Code Downloaded for Programming the Semantic Web (python code)

2014-07-28 Thread Bruce Whealton
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)

2014-07-28 Thread Bruce Whealton
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)

2014-07-28 Thread Steven D'Aprano
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)

2014-07-28 Thread Bruce Whealton
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)

2014-07-26 Thread Terry Reedy

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)

2014-07-25 Thread Bruce Whealton
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)

2014-07-25 Thread Skip Montanaro
 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)

2014-07-25 Thread Dan Stromberg
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)

2014-07-25 Thread Ian Kelly
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)

2014-07-25 Thread Steven D'Aprano
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)

2014-07-25 Thread Chris Angelico
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