printing to stdout

2018-08-16 Thread richard lucassen
I can run a shell script from the commandline as root in which I start
a python script as user "ha". The output to stdout and stderr
generated by the python script is visible in an xterm:

#!/bin/dash
exec 2>&1
chpst -u ha:ha:i2c -U ha /usr/local/ha/init.sh
exec chpst -u ha:ha:i2c:gpio /usr/local/ha/wait4int.py

So far so good. But when I run the script supervised by runit, I can
see the output generated by the shell script "init.sh", but the output
of the python script is not transferred to the supervised logging. The
python script itself works, it reads out some I/O expanders on a
Raspberry Pi. But the output of the "print" commands seems to disappear:

[..]
while True:
  if GPIO.input(23) == 1: # if still 0, another event has occurred
GPIO.wait_for_edge(23, GPIO.FALLING)
  print ('---')
  while GPIO.input(23) == 0:
for pcf in pcf_present:
  output = bus.read_byte(pcf)
  print ("%x: %x" % (pcf, output))
  if GPIO.input(23) == 1:
loopcntr = 0
break
  else:
loopcntr += 1
if loopcntr >=20:
  print ('[ALERT] possible INT loop, disable 10 seconds')
  sleep (10)
GPIO.cleanup()

Anyone a hint? Note: I'm a newbie to python.

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-16 Thread Cameron Simpson

On 16Aug2018 22:37, richard lucassen  wrote:

I can run a shell script from the commandline as root in which I start
a python script as user "ha". The output to stdout and stderr
generated by the python script is visible in an xterm:

#!/bin/dash
exec 2>&1
chpst -u ha:ha:i2c -U ha /usr/local/ha/init.sh
exec chpst -u ha:ha:i2c:gpio /usr/local/ha/wait4int.py

So far so good. But when I run the script supervised by runit, I can
see the output generated by the shell script "init.sh", but the output
of the python script is not transferred to the supervised logging. The
python script itself works, it reads out some I/O expanders on a
Raspberry Pi. But the output of the "print" commands seems to disappear:

[...]

This isn't specific to Python, you'll find it with most programmes. (The 
shell's builtin "echo" command is an exception.)


Some discussion: most output streams are buffered: this means that when you 
issue some kind of "write" operation to them, the output data are copied to a 
buffer area in memory, and only actually written out to the operating system 
(which mediates the data between programmes) at certain times. This reduces the 
OS level data transfers, which is generally a performance win overall.


When are the data sent on to the OS? That depends on the buffered arrangement.  
When the buffer fills, the data are always sent on because otherwise there's no 
room for more data. But otherwise, the data are sent on at specific times.


An unbuffered stream sends the data on immediately. The standard error stream 
is usually unbuffered, so that error messages get out immediately.


A fully buffered stream is sent on only when the buffer fills.

A line buffered stream is sent on when a newline lands in the buffer.

You can of course devise whatever system you like, but these three are the 
common presupplied automatic ones.


Also, you can usually force any buffered data to be send on by flushing the 
buffer.


On UNIX systems, the _default_ behaviour of the standard output stream depends 
on what it is connected to. Stdout is line buffered when connected to a 
terminal and fully buffered otherwise. This generally makes for nice 
interactive behaviour (you see timely output when working interactively) and 
better overall performance when the output is going to a file or a pipe.


So let's look at your script:


 print ("%x: %x" % (pcf, output))

[...]

 print ('[ALERT] possible INT loop, disable 10 seconds')


Your programme will be writing into a buffer. Your messages only go out when 
enough have accrued to fill the buffer.


To force te messages to go out in a timely manner you need to flush the buffer.  
You have two choices here: call sys.stdout.flush() or pass "flush=True" with 
the print call, eg:


 print(, flush=True)

Just looking at your loop I would be inclined to just call flush once at the 
bottom, _before_ the sleep() call:


 sys.stdout.flush()

Your call; the performance difference will be small, so it tends to come down 
to keeping your code readable and maintainable.


Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-17 Thread richard lucassen
On Fri, 17 Aug 2018 08:31:22 +1000
Cameron Simpson  wrote:

> This isn't specific to Python, you'll find it with most programmes.
> (The shell's builtin "echo" command is an exception.)

[buffer explanation]

I already suspectec a buffered output and to check if it was the
buffer, I created a lot of output by pressing the button that generates
an INT quite a lot of times. But apparently this wasn't enough. After
all, the output is small:

---
38: ff
39: ff
3a: ff
3b: fb


I fear I generated 4095 bytes instead of 4096. Some wise human being
once said "Murphy was an optimist" :)

> So let's look at your script:
> 
> >  print ("%x: %x" % (pcf, output))
> [...]
> >  print ('[ALERT] possible INT loop, disable 10 seconds')
> 
> Your programme will be writing into a buffer. Your messages only go
> out when enough have accrued to fill the buffer.
> 
> To force te messages to go out in a timely manner you need to flush
> the buffer. You have two choices here: call sys.stdout.flush() or
> pass "flush=True" with the print call, eg:
> 
>   print(, flush=True)
> 
> Just looking at your loop I would be inclined to just call flush once
> at the bottom, _before_ the sleep() call:
> 
>   sys.stdout.flush()
> 
> Your call; the performance difference will be small, so it tends to
> come down to keeping your code readable and maintainable.

Yep, the "sys.stdout.flush()" did the job :) I had already been mucking
about with file=sys.stderr, but without result, just because of the
fact that stderr is never buffered AFAIK (the supervised script "run"
has an "exec 2>&1")

Anyroad, it works :)

Thnx!

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread richard lucassen
On Fri, 17 Aug 2018 08:31:22 +1000
Cameron Simpson  wrote:

> Just looking at your loop I would be inclined to just call flush once
> at the bottom, _before_ the sleep() call:
> 
>   sys.stdout.flush()
> 
> Your call; the performance difference will be small, so it tends to
> come down to keeping your code readable and maintainable.

This is a working script I made. It initializes the I/O expanders, then
it waits for an INT from these I/O expanders on GPIO23, reads the
contents and sends which bit on which chip went up or down to a fifo
(and stdout for logging)

As I'm new to Python, just this question: are there any unPythony
things in this code?

##

#!/usr/bin/env python3

list_pcf = [0x38, 0x39, 0x3a, 0x3b]
list_pcf_value = []

import sys
from smbus import SMBus
from time import sleep
import RPi.GPIO as GPIO
GPIO.setmode(GPIO.BCM)
bus = SMBus(1)

# initialisation of the input devices:
print ("[INFO] initialisation input devices")
for i in range(len(list_pcf)):
  try:
bus.write_byte(list_pcf[i], 0xff) # set device to 0xff
output = bus.read_byte(list_pcf[i])
list_pcf_value.append(output) # append value to list
print ("found: %d, input value: 0x%x" % (list_pcf[i], output))
  except IOError:
print ("[ALERT] I/O problem device 0x%x (init)" % pcf)
  sys.stdout.flush()

# GPIO 23 set up as input. It is pulled up to stop false signals
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
loopcntr = 0 # detects if INT is kept low

while True:
  if GPIO.input(23) == 1: # if still 0, another event has occurred
GPIO.wait_for_edge(23, GPIO.FALLING)
  print ('---')
  while GPIO.input(23) == 0:
for i in range(len(list_pcf)):
  try:
output = bus.read_byte(list_pcf[i])
if output != list_pcf_value[i]:
  xor = list_pcf_value[i] ^ output
  for l in range(8):
if xor & 0x1:
  updown = (output >> l) & 0x1
  print ("%d bit %d: to %d" % (list_pcf[i],l,updown))
  print("%d %d %d" % (list_pcf[i],l,updown), 
file=open('/mnt/ramdisk/var/lib/ha/events.fifo', 'w'))
xor = xor >> 1
  list_pcf_value[i] = output
  except IOError:
print ("[ALERT] I/O problem device 0x%x" % list_pcf[i])

  if GPIO.input(23) == 1:
loopcntr = 0
break
  else:
loopcntr += 1
if loopcntr >=20:
  print ('[ALERT] possible INT loop, disable 10 seconds')
  sleep (10)
sys.stdout.flush()
GPIO.cleanup()

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Marko Rauhamaa
richard lucassen :
> As I'm new to Python, just this question: are there any unPythony
> things in this code?

Your code looks neat.

>   except IOError:
> print ("[ALERT] I/O problem device 0x%x" % list_pcf[i])

Just double check that simply printing the alert is the correct recovery
from the exception. Should there be additional logic instead of the
fallthrough?


Marko
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Cameron Simpson

On 19Aug2018 09:32, richard lucassen  wrote:

This is a working script I made. It initializes the I/O expanders, then
it waits for an INT from these I/O expanders on GPIO23, reads the
contents and sends which bit on which chip went up or down to a fifo
(and stdout for logging)

As I'm new to Python, just this question: are there any unPythony
things in this code?


There are always unPythonic bits. Even after you've cleaned them all up, since 
people will disagree about the finer points of Pythonicism there will be bits 
both over and under cleaned.



##

#!/usr/bin/env python3

list_pcf = [0x38, 0x39, 0x3a, 0x3b]
list_pcf_value = []

import sys
from smbus import SMBus
from time import sleep
import RPi.GPIO as GPIO


Imports should come before any other code.


GPIO.setmode(GPIO.BCM)
bus = SMBus(1)

# initialisation of the input devices:
print ("[INFO] initialisation input devices")
for i in range(len(list_pcf)):


This is better written as:

 for i, pcf in enumerate(list_pcf):

then you can replace every mention of "list_pcf[i] with "pcf" within the loop.

And in fact, since you're not using "i" for anything else you can just go:

 for pcf in list_pcf:


 try:
   bus.write_byte(list_pcf[i], 0xff) # set device to 0xff
   output = bus.read_byte(list_pcf[i])
   list_pcf_value.append(output) # append value to list
   print ("found: %d, input value: 0x%x" % (list_pcf[i], output))
 except IOError:


It is best to put try/except around the smallest possible piece of code. If 
there is an I/O error in the above you have no idea what caused it. Even the 
print() could emit one, and in that case your except clause's action will be 
misguided. Example:


 try:
   bus.write_byte(list_pcf[i], 0xff) # set device to 0xff
   output = bus.read_byte(list_pcf[i])
 except IOError as e:
   ...
 else:
   list_pcf_value.append(output) # append value to list
   print ("found: %d, input value: 0x%x" % (list_pcf[i], output))


   print ("[ALERT] I/O problem device 0x%x (init)" % pcf)


You should always include the exception itself in this kind of message, 
example:


  print ("[ALERT] I/O problem device 0x%x (init): %s" % (pcf, e))
 

 sys.stdout.flush()

# GPIO 23 set up as input. It is pulled up to stop false signals
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
loopcntr = 0 # detects if INT is kept low

while True:
 if GPIO.input(23) == 1: # if still 0, another event has occurred
   GPIO.wait_for_edge(23, GPIO.FALLING)
 print ('---')
 while GPIO.input(23) == 0:
   for i in range(len(list_pcf)):


You can write thos as:

 for i, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):

and then just talk about "pcf" and "pcf_value" where you have "list_pcf[i]" and 
"list_pcf_value[i]". Then you just want the "i" when you update 
"list_pcf_value[i]". (Assigning to pcf_value won't affect that, so you need the 
index.)



 try:
   output = bus.read_byte(list_pcf[i])


Again, this try/except covers too much code. It should only cover bus I/O 
actions.



   if output != list_pcf_value[i]:
 xor = list_pcf_value[i] ^ output
 for l in range(8):


You might want a more meaningful name than "l", such as "bit_pos".


   if xor & 0x1:
 updown = (output >> l) & 0x1
 print ("%d bit %d: to %d" % (list_pcf[i],l,updown))
 print("%d %d %d" % (list_pcf[i],l,updown),
   file=open('/mnt/ramdisk/var/lib/ha/events.fifo', 'w'))


This print is better written:

 with open('/mnt/ramdisk/var/lib/ha/events.fifo', 'w') as fifo:
   print("%d %d %d" % (list_pcf[i],l,updown), file=fifo)

This ensures timely closing of the fifo when you exit the with suite.

Your "print(, file=open(...))" _will_ close the fifo in a timely fashion in 
CPython because the reference counting will trigger the file's delete action, 
but in other Python implementations the deletion may happen an arbitrarily 
large amount of time later (because they may garbage collect unreferenced 
objects differently).


Importantly, your print() won't get flushed to the fifo until the file closes, 
so timely closing is important. The with is reliable. And also the common 
idiom.



   xor = xor >> 1


You can write this:

 xor >>= 1


 list_pcf_value[i] = output
 except IOError:
   print ("[ALERT] I/O problem device 0x%x" % list_pcf[i])


And again, you should include the exception value in the message.


 if GPIO.input(23) == 1:
   loopcntr = 0
   break
 else:


You don't need this else, because the break will exit the loop.


   loopcntr += 1
   if loopcntr >=20:
 print ('[ALERT] possible INT loop, disable 10 seconds')
 sleep (10)
   sys.stdout.flush()


You need a flush before the sleep, otherwise the flush won't occur for 10 
seconds. Untimely.



GPIO.cleanup()


Cheers,
Cameron Simpson 
--
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread richard lucassen
On Sun, 19 Aug 2018 19:53:04 +1000
Cameron Simpson  wrote:

[Oops, apparently you set the Reply-To to python-list@python.org,
normally that's no problem, but I did something wrong somewhere]

> There are always unPythonic bits. Even after you've cleaned them all
> up, since people will disagree about the finer points of Pythonicism
> there will be bits both over and under cleaned.

Although I do not understand exactly what zip is doing here (I presume
I switch to use pointers instead of the values), I like the
"enumerate" function, very handy :-) The code is now as
follows:

#!/usr/bin/env python3

import sys
from smbus import SMBus
from time import sleep
import RPi.GPIO as GPIO

list_pcf = [0x38, 0x39, 0x3a, 0x3b]
list_pcf_value = []
GPIO.setmode(GPIO.BCM)
bus = SMBus(1)

# initialisation of the input devices:
print ("[INFO] initialisation input devices")
for pcf in list_pcf:
  try:
bus.write_byte(pcf, 0xff) # set device to 0xff
  except IOError as e:
print ("[ALERT] I/O problem device 0x%x (init): %s" % (pcf, e))
  output = bus.read_byte(pcf)
  list_pcf_value.append(output) # append value to list
  print ("found pcf8574 at 0x%x, input value: 0x%x" % (pcf, output))
  sys.stdout.flush()

# GPIO 23 set up as input. It is pulled up to stop false signals
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
loopcntr = 0 # detects if INT is kept low

while True:
  if GPIO.input(23) == 1: # if still 0, another event has occurred
GPIO.wait_for_edge(23, GPIO.FALLING)

  while GPIO.input(23) == 0:
for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):
  try:
output = bus.read_byte(pcf)
  except IOError as e:
print ("[ALERT] I/O problem device 0x%x: %s" % (pcf, e))

  if output != pcf_value:
xor = pcf_value ^ output
for bit_pos in range(8):
  if xor & 0x1:
up_down = (output >> bit_pos) & 0x1
print ("pcf8574 0x%x bit %d: to %d" % (pcf,bit_pos,up_down))
# send decimal values to event script:
with open('/mnt/ramdisk/var/lib/ha/events.fifo', 'w') as fifo:
  print("%d %d %d" % (pcf,bit_pos,up_down), file=fifo)
  xor >>= 1
list_pcf_value[device_nr] = output

  if GPIO.input(23) == 1:
loopcntr = 0
break
  loopcntr += 1
  if loopcntr >=20:
print ('[ALERT] possible INT loop, disabling 10 seconds')
sys.stdout.flush()
sleep (10)

sys.stdout.flush()
GPIO.cleanup()

And it still works :-)

Thnx!

R.


-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread richard lucassen
On Sun, 19 Aug 2018 12:02:51 +0300
Marko Rauhamaa  wrote:

> richard lucassen :
> > As I'm new to Python, just this question: are there any unPythony
> > things in this code?
> 
> Your code looks neat.

Well, apparently there were quite a lot of things that makes the code
more readable I'd say. And even better. But it was indeed not very
unPythony. OTOH, I'm not a programmer, otherwise I would have written
this in C ;-)

R.

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Joel Goldstick
On Sun, Aug 19, 2018 at 9:56 AM richard lucassen
 wrote:
>
> On Sun, 19 Aug 2018 12:02:51 +0300
> Marko Rauhamaa  wrote:
>
> > richard lucassen :
> > > As I'm new to Python, just this question: are there any unPythony
> > > things in this code?
> >
> > Your code looks neat.
>
> Well, apparently there were quite a lot of things that makes the code
> more readable I'd say. And even better. But it was indeed not very
> unPythony. OTOH, I'm not a programmer, otherwise I would have written
> this in C ;-)

This strikes me as an odd conclusion.  Raspberry Pi places a strong
emphasis on python.  It certainly doesn't execute as fast as C can,
but it provides a conceptually higher level programming model.  There
is extremely good community support for python with Pi (a huge plus),
and the code is much more understandable.  It is faster to write code
with python, you can come back to it and understand it more readily at
some later time, as can others.  And it runs 'fast enough' .  So, no,
I don't think if you were a 'programmer' you would have used C to do
this project.  But others may be of a different persuation.

>
> R.

You seemed to have snipped your question about zip function.  It takes
iterables (things like lists, tuples, dictionaries) as arguments and
pairs them together to form tuples.  Look it up.  Very useful.  As and
example, if you have list1 = (1,2,3), and list2 = (4,5,6,7) and zip
them you will get ((1,4), (2,5),(3,6)).  (It stops when the shortest
iterable is exhausted)

Your allusion to pointers is misguided.  Python is not like C or
assembler.  You don't, and don't need to know where objects are
stored.  Names are assigned to reference data objects
>
> --
> richard lucassen
> http://contact.xaq.nl/
> --
> https://mail.python.org/mailman/listinfo/python-list



-- 
Joel Goldstick
http://joelgoldstick.com/blog
http://cc-baseballstats.info/stats/birthdays
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread richard lucassen
On Sun, 19 Aug 2018 19:53:04 +1000
Cameron Simpson  wrote:

> There are always unPythonic bits. Even after you've cleaned them all
> up, since people will disagree about the finer points of Pythonicism
> there will be bits both over and under cleaned.

Although I do not understand what zip is doing exactly here (I presume
I switch to use pointers instead of the values), I like the
"enumerate" function, very handy :-) The code is now as
follows:

#!/usr/bin/env python3

import sys
from smbus import SMBus
from time import sleep
import RPi.GPIO as GPIO

list_pcf = [0x38, 0x39, 0x3a, 0x3b]
list_pcf_value = []
GPIO.setmode(GPIO.BCM)
bus = SMBus(1)

# initialisation of the input devices:
print ("[INFO] initialisation input devices")
for pcf in list_pcf:
  try:
bus.write_byte(pcf, 0xff) # set device to 0xff
  except IOError as e:
print ("[ALERT] I/O problem device 0x%x (init): %s" % (pcf, e))
  output = bus.read_byte(pcf)
  list_pcf_value.append(output) # append value to list
  print ("found pcf8574 at 0x%x, input value: 0x%x" % (pcf, output))
  sys.stdout.flush()

# GPIO 23 set up as input. It is pulled up to stop false signals
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
loopcntr = 0 # detects if INT is kept low

while True:
  if GPIO.input(23) == 1: # if still 0, another event has occurred
GPIO.wait_for_edge(23, GPIO.FALLING)

  while GPIO.input(23) == 0:
for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):
  try:
output = bus.read_byte(pcf)
  except IOError as e:
print ("[ALERT] I/O problem device 0x%x: %s" % (pcf, e))

  if output != pcf_value:
xor = pcf_value ^ output
for bit_pos in range(8):
  if xor & 0x1:
up_down = (output >> bit_pos) & 0x1
print ("pcf8574 0x%x bit %d: to %d" % (pcf,bit_pos,up_down))
# send decimal values to event script:
with open('/mnt/ramdisk/var/lib/ha/events.fifo', 'w') as fifo:
  print("%d %d %d" % (pcf,bit_pos,up_down), file=fifo)
  xor >>= 1
list_pcf_value[device_nr] = output

  if GPIO.input(23) == 1:
loopcntr = 0
break
  loopcntr += 1
  if loopcntr >=20:
print ('[ALERT] possible INT loop, disabling 10 seconds')
sys.stdout.flush()
sleep (10)

sys.stdout.flush()
GPIO.cleanup()

And it still works :-)

Thnx!

R.

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Richard Lucassen
On Sun, 19 Aug 2018 10:11:08 -0400
Joel Goldstick  wrote:

> > Well, apparently there were quite a lot of things that makes the
> > code more readable I'd say. And even better. But it was indeed not
> > very unPythony. OTOH, I'm not a programmer, otherwise I would have
> > written this in C ;-)
> 
> This strikes me as an odd conclusion.  Raspberry Pi places a strong
> emphasis on python.  It certainly doesn't execute as fast as C can,
> but it provides a conceptually higher level programming model.  There
> is extremely good community support for python with Pi (a huge plus),
> and the code is much more understandable.  It is faster to write code
> with python, you can come back to it and understand it more readily at
> some later time, as can others.  And it runs 'fast enough' .  So, no,
> I don't think if you were a 'programmer' you would have used C to do
> this project.  But others may be of a different persuation.

You've got absolutely a point that Python seems to be largely supported
for Rpi. But I'll tell you something else: I just started to use a
Rpi ;-) I agree that python code is much more understandable than C.
 
> You seemed to have snipped your question about zip function.  It takes
> iterables (things like lists, tuples, dictionaries) as arguments and
> pairs them together to form tuples.  Look it up.  Very useful.  As and
> example, if you have list1 = (1,2,3), and list2 = (4,5,6,7) and zip
> them you will get ((1,4), (2,5),(3,6)).  (It stops when the shortest
> iterable is exhausted)
> 
> Your allusion to pointers is misguided.  Python is not like C or
> assembler.  You don't, and don't need to know where objects are
> stored.  Names are assigned to reference data objects

I'll have another look at it, I was just searching for a clear
explanation, but the page I found was not clear enough for me. I'll
have to take some time for it...

-- 
Richard Lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Joel Goldstick
On Sun, Aug 19, 2018 at 12:16 PM Richard Lucassen
 wrote:
>
> On Sun, 19 Aug 2018 10:11:08 -0400
> Joel Goldstick  wrote:
>
> > > Well, apparently there were quite a lot of things that makes the
> > > code more readable I'd say. And even better. But it was indeed not
> > > very unPythony. OTOH, I'm not a programmer, otherwise I would have
> > > written this in C ;-)
> >
> > This strikes me as an odd conclusion.  Raspberry Pi places a strong
> > emphasis on python.  It certainly doesn't execute as fast as C can,
> > but it provides a conceptually higher level programming model.  There
> > is extremely good community support for python with Pi (a huge plus),
> > and the code is much more understandable.  It is faster to write code
> > with python, you can come back to it and understand it more readily at
> > some later time, as can others.  And it runs 'fast enough' .  So, no,
> > I don't think if you were a 'programmer' you would have used C to do
> > this project.  But others may be of a different persuation.
>
> You've got absolutely a point that Python seems to be largely supported
> for Rpi. But I'll tell you something else: I just started to use a
> Rpi ;-) I agree that python code is much more understandable than C.
>
> > You seemed to have snipped your question about zip function.  It takes
> > iterables (things like lists, tuples, dictionaries) as arguments and
> > pairs them together to form tuples.  Look it up.  Very useful.  As and
> > example, if you have list1 = (1,2,3), and list2 = (4,5,6,7) and zip
> > them you will get ((1,4), (2,5),(3,6)).  (It stops when the shortest
> > iterable is exhausted)
> >
> > Your allusion to pointers is misguided.  Python is not like C or
> > assembler.  You don't, and don't need to know where objects are
> > stored.  Names are assigned to reference data objects
>
> I'll have another look at it, I was just searching for a clear
> explanation, but the page I found was not clear enough for me. I'll
> have to take some time for it...

try python.org tutorial, and search for terms like names, or name
binding.  And also 'namespace'

> --
> Richard Lucassen
> http://contact.xaq.nl/
> --
> https://mail.python.org/mailman/listinfo/python-list



-- 
Joel Goldstick
http://joelgoldstick.com/blog
http://cc-baseballstats.info/stats/birthdays
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Richard Lucassen
On Sun, 19 Aug 2018 12:37:18 -0400
Joel Goldstick  wrote:

> > I'll have another look at it, I was just searching for a clear
> > explanation, but the page I found was not clear enough for me. I'll
> > have to take some time for it...
> 
> try python.org tutorial, and search for terms like names, or name
> binding.  And also 'namespace'

I'll have to get used to the language and I think it's a nice language.
I just mucked about with the sqlite modules BTW. And it works :) 

-- 
Richard Lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Cameron Simpson

On 19Aug2018 18:10, richard lucassen  wrote:

On Sun, 19 Aug 2018 10:11:08 -0400
Joel Goldstick  wrote:

Your allusion to pointers is misguided.  Python is not like C or
assembler.  You don't, and don't need to know where objects are
stored.  Names are assigned to reference data objects


I'll have another look at it, I was just searching for a clear
explanation, but the page I found was not clear enough for me. I'll
have to take some time for it...


If you think of references like C pointers you are 80% of the way there.

In CPython (the primary Python implementation, which you're using), a reference 
is effectively a pointer to the referenced Python object. _Internally_. And the 
result of the id() function (giving an object's identity) _happens_ to be a 
memory address.


But the language specification doesn't talk about pointers or memory addresses, 
and other implementations may use other abstractions to associate variables 
with the objects they reference.


So never talk about Python references as pointers. You'll cop noisy criticism!

Just think of them as arrows from a variable (or attributes, etc) to an object.

Every Python variable is a reference. So when you pass a variable to a function 
or use it in an expression, your putting a reference there. This:


 x = 3
 y = x

results in x and y referring to the same "3" int object. For ints this is 
pretty irrelevant, since they're immutable. Arithmetic works as you would 
expect.


But this:

 values = [1, 2, 3]
 values2 = values

Here, values and values 2 both refer to the same list - values2 does not have a 
copy. So:


 values2[1] = 4

means that values[1] and values2[1] are both 4 because it is the same list.

Cheers,
Cameron Simpson 

Draw little boxes with arrows.  It helps.   - Michael J. Eager
--
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Chris Angelico
On Mon, Aug 20, 2018 at 7:55 AM, Cameron Simpson  wrote:
> Draw little boxes with arrows.  It helps.   - Michael J. Eager

Draw good boxes. - DeviCat

ChrisA
-- 
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-19 Thread Cameron Simpson

On 19Aug2018 15:09, richard lucassen  wrote:

On Sun, 19 Aug 2018 19:53:04 +1000
Cameron Simpson  wrote:
Although I do not understand what zip is doing exactly here (I presume
I switch to use pointers instead of the values),


Someone else has descibed zip tersely: it pairs it the elements of 2 lists. In 
fact it joins up matching elements of an arbitrary number of iterables. Here is 
a 3 iterable example:


   >>> zip( (1,2,3), (4,5,6), (7,8,9) )
   
   >>> list( zip( (1,2,3), (4,5,6), (7,8,9) ) )
   [(1, 4, 7), (2, 5, 8), (3, 6, 9)]

See that is has collected the first element of each tuple, then the second and 
so forth?


In my sentence above, "iterable" means any object you can iterate over - any 
object you could use in a for-loop. So, obviously, a list as in your programme.  
And also a tuple like (1,2,3) as in the example above (a tuple is an 
unmodifiable list). ANd any number of other things that will yield a sequence 
of values.


In Python 3 (which you're using) zip returns a lazy object, which does the 
zipping as you request the values. That is why the example shows a base "zip()" 
returning a "zip object" - we hand it to list() to get an actual list of all 
the values. This is fast (instant return of the zip object without doing much 
work) and cheap in memory (no need to make a huge result if you're zipping big 
lists) and cheap in time (no need to make the whole result if you're only using 
the first part of it).


So, to the code using the zip:

 for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):

The inner zip yields (pcf, pcf_value) pairs from zipping list_pcf and 
list_pcf_value, an iterable of:


 (pcf[0], pcf-value[0]), (pcf[1], pcf_value[1]), ...

and you can write a for loop like this:

 for pcf, pcf_value in zip(list_pcf, list_pcf_value):

to deal with each of those pairs in turn.

However, since you also need the index (device_nr) in order to update 
list_pcf_value:


 list_pcf_value[device_nr] = output

we then hand the whole thing to enumerate:

 for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):

The enumerate does just what the previous one did, yields pairs of (index, 
value). Each value is a pair from the zip, so it yields:


 (0, (pcf[0], pcf-value[0])),
 (1, (pcf[1], pcf_value[1])),
 ...

and Python's tuple unpacking syntax is fairly generous, so you want write:

 device_nr, (pcf, pcf_value) = (0, (pcf[0], pcf-value[0]))

and you can stick that in the for loop, getting the syntax you're using in the 
programme:


 for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf, list_pcf_value)):


The code is now as follows:


Much nicer. A few tiny nit picks:


#!/usr/bin/env python3

import sys
from smbus import SMBus
from time import sleep
import RPi.GPIO as GPIO

list_pcf = [0x38, 0x39, 0x3a, 0x3b]
list_pcf_value = []


Just convention: you could call these pcfs and pcf_values and perhaps have more 
readable code. Using plural names kind of indicates that they're lists (or 
tuples or some other sequence of values) and reads more like prose.



# initialisation of the input devices:
print ("[INFO] initialisation input devices")


"print" is just a regular function. We tend not to put a space before the "(" 
with other functions, and print isn't special. You might have this trailing 
space left over from Python 2 (either your own or some example code), where 
print _wasn't_ a function. So:


 print("[INFO] initialisation input devices")


for pcf in list_pcf:
 try:
   bus.write_byte(pcf, 0xff) # set device to 0xff
 except IOError as e:
   print ("[ALERT] I/O problem device 0x%x (init): %s" % (pcf, e))
 output = bus.read_byte(pcf)


You presumably also want a try/except around the bus.read_byte. You could use a 
distinct try/except (rather wordy) or, since they're adjacent and your 
exception action is the same, just put them both inside the try/except.


The advice to keep things as small as possible within the try/except has to do 
with knowing exactly what kind of thing threw the exception. But they're both 
bus operations and handled the same - including both is reasonable.



 list_pcf_value.append(output) # append value to list
 print ("found pcf8574 at 0x%x, input value: 0x%x" % (pcf, output))
 sys.stdout.flush()
# GPIO 23 set up as input. It is pulled up to stop false signals
GPIO.setup(23, GPIO.IN, pull_up_down=GPIO.PUD_UP)
loopcntr = 0 # detects if INT is kept low

while True:
 if GPIO.input(23) == 1: # if still 0, another event has occurred
   GPIO.wait_for_edge(23, GPIO.FALLING)


Can the GPIO ops also raise IOErrors? Just wondering.

Cheers,
Cameron Simpson 

Stepwise Refinement n.  A sequence of kludges K, neither distinct or finite,
applied to a program P aimed at transforming it into the target program Q.
--
https://mail.python.org/mailman/listinfo/python-list


Re: printing to stdout

2018-08-23 Thread richard lucassen
On Mon, 20 Aug 2018 08:19:12 +1000
Cameron Simpson  wrote:

[sorry for late reply]

> Someone else has descibed zip tersely: it pairs it the elements of 2
> lists. In fact it joins up matching elements of an arbitrary number
> of iterables. Here is a 3 iterable example:
> 
> >>> zip( (1,2,3), (4,5,6), (7,8,9) )
> 
> >>> list( zip( (1,2,3), (4,5,6), (7,8,9) ) )
> [(1, 4, 7), (2, 5, 8), (3, 6, 9)]
> 
> See that is has collected the first element of each tuple, then the
> second and so forth?

Yep, an image or an example says more than 1000 pages of explanation
 
> In my sentence above, "iterable" means any object you can iterate
> over - any object you could use in a for-loop. So, obviously, a list
> as in your programme. And also a tuple like (1,2,3) as in the example
> above (a tuple is an unmodifiable list). ANd any number of other
> things that will yield a sequence of values.
> 
> In Python 3 (which you're using) zip returns a lazy object, which
> does the zipping as you request the values. That is why the example
> shows a base "zip()" returning a "zip object" - we hand it to list()
> to get an actual list of all the values. This is fast (instant return
> of the zip object without doing much work) and cheap in memory (no
> need to make a huge result if you're zipping big lists) and
> cheap in time (no need to make the whole result if you're only using
> the first part of it).
> 
> So, to the code using the zip:
> 
>   for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf,
> list_pcf_value)):
> 
> The inner zip yields (pcf, pcf_value) pairs from zipping list_pcf and 
> list_pcf_value, an iterable of:
> 
>   (pcf[0], pcf-value[0]), (pcf[1], pcf_value[1]), ...
> 
> and you can write a for loop like this:
> 
>   for pcf, pcf_value in zip(list_pcf, list_pcf_value):
> 
> to deal with each of those pairs in turn.
> 
> However, since you also need the index (device_nr) in order to update 
> list_pcf_value:
> 
>   list_pcf_value[device_nr] = output
> 
> we then hand the whole thing to enumerate:
> 
>   for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf,
> list_pcf_value)):
> 
> The enumerate does just what the previous one did, yields pairs of
> (index, value). Each value is a pair from the zip, so it yields:
> 
>   (0, (pcf[0], pcf-value[0])),
>   (1, (pcf[1], pcf_value[1])),
>   ...
> 
> and Python's tuple unpacking syntax is fairly generous, so you want
> write:
> 
>   device_nr, (pcf, pcf_value) = (0, (pcf[0], pcf-value[0]))
> 
> and you can stick that in the for loop, getting the syntax you're
> using in the programme:
> 
>   for device_nr, (pcf, pcf_value) in enumerate(zip(list_pcf,
> list_pcf_value)):

Well, that's a nice and clear explanation, at the prompt I played a bit
with the enumerate and zip functions and after all it's quite simple :)

> >The code is now as follows:
> 
> Much nicer. A few tiny nit picks:

[..] changes applied

> >while True:
> >  if GPIO.input(23) == 1: # if still 0, another event has occurred
> >GPIO.wait_for_edge(23, GPIO.FALLING)
> 
> Can the GPIO ops also raise IOErrors? Just wondering.

Probably, sounds logigal, the GPIO pin is read and if something is
wrong it will generate an I/O error. 

R.

-- 
richard lucassen
http://contact.xaq.nl/
-- 
https://mail.python.org/mailman/listinfo/python-list


help with printing to stdout...

2009-03-08 Thread Daniel Dalton
Hi,

I've got a program here that prints out a percentage of it's
completion. Currently with my implimentation it prints like this:
0%
1%
2%
3%
4%

etc taking up lots and lots of lines of output... So, how can I make it
write the percentage on the same line eg. 
while working:
  print percent
every time the line print percent is ran it should delete the old
percentage from the screen, replacing it with the new one, so as to only
use up one line... Basically I'm just printing a string of text to the
screen and every time my print command is ran I would like the old text
to be removed and my new text added (talking about the one line of the
screen here)... This is a command line program, under linux...

Thanks,

Daniel.
--
http://mail.python.org/mailman/listinfo/python-list


Re: help with printing to stdout...

2009-03-08 Thread Chris Rebert
On Sun, Mar 8, 2009 at 1:37 AM, Daniel Dalton  wrote:
> Hi,
>
> I've got a program here that prints out a percentage of it's
> completion. Currently with my implimentation it prints like this:
> 0%
> 1%
> 2%
> 3%
> 4%
>
> etc taking up lots and lots of lines of output... So, how can I make it
> write the percentage on the same line eg.
> while working:
>  print percent

Use the carriage return character to overwrite the line (you'll need
to forego `print`):

from sys import stdout
while working:
stdout.write('\r'+percent)

Note that you'll need to ensure that `percent` has constant length
throughout the loop.

Cheers,
Chris

-- 
I have a blog:
http://blog.rebertia.com
--
http://mail.python.org/mailman/listinfo/python-list


Re: help with printing to stdout...

2009-03-08 Thread D'Arcy J.M. Cain
On Sun, 8 Mar 2009 01:59:03 -0800
Chris Rebert  wrote:
> > etc taking up lots and lots of lines of output... So, how can I make it
> > write the percentage on the same line eg.
> Use the carriage return character to overwrite the line (you'll need
> to forego `print`):

Why do you say that?

> from sys import stdout
> while working:
> stdout.write('\r'+percent)

while working:
  print '\r'+percent,

> Note that you'll need to ensure that `percent` has constant length
> throughout the loop.

Nope.  You just need to make sure that it never gets shorter which is
the case here.  If it wasn't then:

while working:
  print '\r'+percent+' ',

-- 
D'Arcy J.M. Cain  |  Democracy is three wolves
http://www.druid.net/darcy/|  and a sheep voting on
+1 416 425 1212 (DoD#0082)(eNTP)   |  what's for dinner.
--
http://mail.python.org/mailman/listinfo/python-list


Re: help with printing to stdout...

2009-03-08 Thread Hendrik van Rooyen
"Daniel Dalton"  wrote:

> I've got a program here that prints out a percentage of it's
> completion. Currently with my implimentation it prints like this:
> 0%
> 1%
> 2%
> 3%
> 4%
> 
> etc taking up lots and lots of lines of output... So, how can I make it
> write the percentage on the same line eg. 
> while working:
>   print percent
> every time the line print percent is ran it should delete the old
> percentage from the screen, replacing it with the new one, so as to only
> use up one line... Basically I'm just printing a string of text to the
> screen and every time my print command is ran I would like the old text
> to be removed and my new text added (talking about the one line of the
> screen here)... This is a command line program, under linux...

Play with the following:

put a comma after the print, like this:

print percent,#This keeps it on the same line

Then put a carriage return at the start, like this:

print '\r',percent,

or like this:

print '\r'+str(percent),

Then make sure it gets sent out, like this:

sys.stdout.flush()

Alternatively, you can play with backspaces instead of the carriage return:

print '\b\b\b\b',
print percent,
sys.stdout.flush()

And see what happens.

- Hendrik


--
http://mail.python.org/mailman/listinfo/python-list


Re: help with printing to stdout...

2009-03-08 Thread Lie Ryan

Chris Rebert wrote:

On Sun, Mar 8, 2009 at 1:37 AM, Daniel Dalton  wrote:

Hi,

I've got a program here that prints out a percentage of it's
completion. Currently with my implimentation it prints like this:
0%
1%
2%
3%
4%

etc taking up lots and lots of lines of output... So, how can I make it
write the percentage on the same line eg.
while working:
 print percent


Use the carriage return character to overwrite the line (you'll need
to forego `print`):

from sys import stdout
while working:
stdout.write('\r'+percent)

Note that you'll need to ensure that `percent` has constant length
throughout the loop.



or "erase" the previous character first with whitespace
stdout.write('\r\r%s%%' % percent).

curse might be more reliable for this kind of thing (though it is 
definitely an overkill)


Note: \r doesn't work on IDLE
--
http://mail.python.org/mailman/listinfo/python-list


Re: help with printing to stdout...

2009-03-08 Thread Daniel Dalton
> or like this:
> 
> print '\r'+str(percent),
> 
> Then make sure it gets sent out, like this:
> 
> sys.stdout.flush()

Hey!

Thanks very much, that did the trick!

Thanks to everyone that replied, I discovered converting to str was
crutial to actually print anything. :)

Cheers,

Daniel.
--
http://mail.python.org/mailman/listinfo/python-list