[Tutor] Passing Data to .DLL

2014-10-22 Thread Wilson, Pete
I am having problems passing a pointer and uint8 to a .DLL. I have been 
successful registering call -backs with this .DLL. So it is all 32-bit and 
ctypes are working. Everything is working up to the line #set-up 
ProcessingIncomingSerialData. I tried the direct approach and then morphing the 
call-back style but yummy_thing is not so yummy... The python code is below..

The definition from the .DLL header is
[cid:image002.png@01CFED51.0C6D7E70]

# Python code starts here.

''' read_bat.py
'''

from serial import *
from string import *
from time import *

system_state = "G2G"

''' --- REMOVED Set-up the COMM port 
print("Enter COM port number")
user_comm_port = raw_input()

try:
dut_serial_port = Serial(port="COM"+user_comm_port, baudrate=115200, 
timeout=1)
except:
system_state = "FUBAR"
print "Serial Port Problem"

try:
dut_serial_port.isOpen()
print("COM" + user_comm_port + " is open")
except:
print "Serial Port Problem"
system_state = "FUBAR"

---'''

#Set-up and register cb_send_serial_data

from ctypes import *

pt_dll = CDLL("c:/py_stuff/ProductionTest.dll")

SendSerialData_t = CFUNCTYPE(None, POINTER(c_uint8), c_uint8)

reg_send_serial_data = pt_dll.RegSendSerialData
reg_send_serial_data.argtypes = [SendSerialData_t]
reg_send_serial_data.restype = None


global new_serial_tx_data
global new_serial_size

def send_serial_data(tx_data, size):
# testing
print "tx_data = ", tx_data
print "size = ", size
print "tx_data[:size] = ", tx_data[:size]

global new_serial_tx_data
new_serial_tx_data = tx_data[:size]

global new_serial_size
new_serial_size = size

cb_send_serial_data = SendSerialData_t(send_serial_data)
global cb_send_serial_data

reg_send_serial_data(cb_send_serial_data)

print "reg_send_serial_data done"

#Set-up and register cb_bat_vol_read
#this triggers send_serial_data when it is registered.


BatVolReadRequest_t = CFUNCTYPE(None, c_uint16, c_uint8)

prod_bat_vol_read_request = pt_dll.ProdBatVolReadRequest
prod_bat_vol_read_request.argtypes = [BatVolReadRequest_t]
prod_bat_vol_read_request.restype = None

def bat_vol_read(bat_vol, status):
print "bat_vol_read()"
# testing
print bat_vol, status

cb_bat_vol_read = BatVolReadRequest_t(bat_vol_read)

prod_bat_vol_read_request(cb_bat_vol_read)

print "prod_bat_vol_read_request done"


''' REMOVED serial access for example -
#push new_serial_tx_data  out the serial port to the DUT.

print new_serial_tx_data

dut_serial_port.write(new_serial_tx_data)
dut_serial_port.write("\r \n")
sleep(1)


#and check to see the DUT's reply...


global new_serial_rx_data
#new_serial_rx_data =""
global rx_buf
rx_buf = []

try:
string_buf = dut_serial_port.readline()
except:
system_state = "FUBAR"
print "serial read problem"

rx_buf = list(string_buf)
print "string_buf = ", string_buf
print "rx_buf = ", rx_buf

---'''

#set-up ProcessingIncomingSerialData

print "breakpoint"

class rx_data_t:
def _init_(self):
#self.ret = None
self.data = []
self.size = ''

fake_rx_data = rx_data_t()

fake_rx_data.data = ['\x01', '\x05', '\x00', '\x1c', '\x00', '\x99', '\x0c', 
'\x04']
fake_rx_data.size = 8

print "fake_rx_data.data = ", fake_rx_data.data
print "fake_rx_data.size = ", fake_rx_data.size

ProcessIncomingSerialData_t = CFUNCTYPE(None, POINTER(c_uint8), c_uint16)

process_incoming_serial_data = pt_dll.ProcessIncomingSerialData
process_incoming_serial_data.argtypes = [ProcessIncomingSerialData_t]
#process_incoming_serial_data.argtypes = [POINTER(c_uint8), c_uint16]
process_incoming_serial_data.restype = None

yummy_thing = ProcessIncomingSerialData_t(fake_rx_data)passing pointers to

process_incoming_serial_data(yummy_thing)
#process_incoming_serial_data(fake_rx_data)

print "Done."
print "system_state = ", system_state
#print "Closing COM port", user_comm_port
#dut_serial_port.close()
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] A couple of somewhat esoteric questions

2014-10-22 Thread Clayton Kirkwood
As I've contemplated the usage of dictionaries, I face the question of
efficiency. Going back before most of you were probably born;<)) if I
remember correctly dictionaries(assoc. arrays), having hashes, are efficient
for storing sparse arrays with the added benefit of hiding the traversal of
the dictionary looking for the proper key, and being much less efficient if
looking for the value and trying to retrieve its key. But it also depends on
the hash key and algorithm and how many spaces are "available" for filling.
If a hash is created for a small array, which is known ahead of time with
some possible hints, the array is efficient but has the distinct difficulty
of use when more and more pairs are created, because either the new pair
matches an already used hash point and a trail must be descended off of that
particular hash point or a mechanism must be used to determine how the new
pair should be stored elsewhere in the array like at the end and matching
becomes time consuming. And/or, a new hash key and perhaps a different
algorithm must be used for creating the larger array. Also, since the array
allows for multiple keys pointing to possibly identical values, the array is
not necessarily 1 to 1 (could be 1 to multiple although we use replacement
of the value normally) and definitely cannot be onto: there is no rule that
says the mapping from value back to key is singular and unique.

 

I've not had much use of dictionaries in the past so maybe I am missing
something. As I contemplated dictionary use, it seems changing the order of
entries is best left to double single arrays - which can be modified
together when changing order. Dicts don't seem to support moving pairs
around and in fact would be broken if changes were attempted. Kind of like
using a real dictionary, you can have a word (key) have multiple meanings
(values), and you can have multiple words (keys) having the same meaning
(value). Again, with the difference from a real dictionary, our dicts can't
have keys pointing to different values. But there are definitely uses for
dicts.

 

Seem right???

 

Clayton

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] yet another misunderstanding on my part

2014-10-22 Thread Clayton Kirkwood
__author__ = 'SYSTEM'

import string

#PricingDividends

raw_table = ('''

a: Asky: Dividend Yield

b: Bid d: Dividend per Share

b2: Ask (Realtime)   r1: Dividend Pay Date

b3: Bid (Realtime)q: Ex-Dividend Date

p: Previous Close

o: Open

 

import re, string

col_position, code, description = 0, [], []

key_name = raw_table.replace('\t','\n')

for each_line in  key_name.splitlines():

if ':' in each_line:

   code[col_position], description.append()  = each_line.split(':')
#neither works; first one is out of range error, 2nd, can't assign to

 
#function. I've used square brackets around various sections, and it doesn't
like it

c, d = each_line.split(':')
#this works

code[col_position] =  each_line.split(':')#why doesn't this.
It looks like what is in the tutorial 5.1. I get out of range error

code.append(c)
#part of the first 'this works' line

code[col_position] = 5
#this works, yet I am using the same col_position element

description.append(d)

print( col_position, code[col_position], description[col_position])

col_position += 1

 

I've seen an example of description.strip() work from a for in loop
assignment with out the can't assign to function.

I'd like to see something like:

code[col_position].strip(), description[col_position].stripe() =
each_line.split(':')

but for some reason, the [col_position] doesn't work, and I can't strip().

 

What am I not seeing? I *do* spend hours trying different options, and study
various documentation which confuse me and don't seem consistent.

 

Thanks,

 

Clayton

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Passing Data to .DLL

2014-10-22 Thread Alan Gauld

On 22/10/14 01:04, Wilson, Pete wrote:

The python code is below..

''' read_bat.py
'''


You are using triple quoted strings as a commenting feature.
Thats good practice where you want a docstring to appear in
the help() screen but its not so good for comments like the
above or where you are commenting out code blocks because
the quotes are esy to miss and hard to spot the closing
match.  (OK in an IDE because it colours the string but
in a mail message its much harder to see)

Could you, when posting long bits of code, please remove
the commented out sections - it makes us (well me at least)
much more willing to study the code. I've tried to remove
the redundant sections below, and made a few style comments.
But apart from the spurious 'comment' at the end of the
calling line I don't see anything obvious.


from serial import *
from string import *


Are you sure you need string? It is very rarely used and I
don't see it anywhere in your code?


from time import *


Also in general its bad practice to use this style of import.
The risk of name collisions is quite high. If you don;t like the long 
names use an alias:


import serial as ser

for example.


system_state = "G2G"

#Set-up and register cb_send_serial_data
from ctypes import *


And its best to keep the imports all together


pt_dll = CDLL("c:/py_stuff/ProductionTest.dll")
SendSerialData_t = CFUNCTYPE(None, POINTER(c_uint8), c_uint8)

reg_send_serial_data = pt_dll.RegSendSerialData
reg_send_serial_data.argtypes = [SendSerialData_t]
reg_send_serial_data.restype = None

global new_serial_tx_data
global new_serial_size


You don't need the global keyword at the module level,
its only needed inside the function to indicate that
the variable is non-local.


def send_serial_data(tx_data, size):
 # testing
 print "tx_data = ", tx_data
 print "size = ", size
 print "tx_data[:size] = ", tx_data[:size]

 global new_serial_tx_data

 new_serial_tx_data = tx_data[:size]

 global new_serial_size


Its traditional to put all the global declarations together
at the top of the function.


 new_serial_size = size

cb_send_serial_data = SendSerialData_t(send_serial_data)
global cb_send_serial_data
reg_send_serial_data(cb_send_serial_data)
print "reg_send_serial_data done"

#Set-up and register cb_bat_vol_read
#this triggers send_serial_data when it is registered.

BatVolReadRequest_t = CFUNCTYPE(None, c_uint16, c_uint8)
prod_bat_vol_read_request = pt_dll.ProdBatVolReadRequest
prod_bat_vol_read_request.argtypes = [BatVolReadRequest_t]
prod_bat_vol_read_request.restype = None

def bat_vol_read(bat_vol, status):
 print "bat_vol_read()"
 print bat_vol, status

cb_bat_vol_read = BatVolReadRequest_t(bat_vol_read)

prod_bat_vol_read_request(cb_bat_vol_read)
print "prod_bat_vol_read_request done"

#set-up ProcessingIncomingSerialData

print "breakpoint"

class rx_data_t:
 def _init_(self):
 self.data = []
 self.size = ''

fake_rx_data = rx_data_t()
fake_rx_data.data = ['\x01', '\x05', '\x00', '\x1c', '\x00', '\x99',
'\x0c', '\x04']
fake_rx_data.size = 8


I'm not sure why you used a class here. But if you are
using one you might as well make the __init__() do
something useful:

class rx_data_t:
def _init_(self,data=[],size=None):
self.data = data
self.size = size

And then initialize it on creation:

fake_rx_data = rx_data_t(['\x01','\x05','\x00','\x1c',
  '\x00','\x99', '\x0c','\x04'],
  8)

But since the class doesn't do anything(no methods)
you might as well just use a tuple or dictionary.

fake_rx_data = {data: ['\x01','\x05','\x00','\x1c',
   '\x00','\x99', '\x0c','\x04'],
size: 8}



print "fake_rx_data.data = ", fake_rx_data.data
print "fake_rx_data.size = ", fake_rx_data.size

ProcessIncomingSerialData_t = CFUNCTYPE(None, POINTER(c_uint8), c_uint16)
process_incoming_serial_data = pt_dll.ProcessIncomingSerialData
process_incoming_serial_data.argtypes = [ProcessIncomingSerialData_t]
process_incoming_serial_data.restype = None

yummy_thing = ProcessIncomingSerialData_t(fake_rx_data)passing pointers to


Is there supposed to be comment marker after the parens?


process_incoming_serial_data(yummy_thing)
print "Done."
print "system_state = ", system_state


--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] A couple of somewhat esoteric questions

2014-10-22 Thread Alan Gauld

On 22/10/14 00:54, Clayton Kirkwood wrote:

As I’ve contemplated the usage of dictionaries, I face the question of
efficiency.


Don;t worry about it. Python dictionaries are highly efficient and used 
throughout the language. namespaces and classes are both effectively 
dictionaries so every time you use a variable name or class attribute 
(whether your own or a built-in) you are using a dictionary.



remember correctly dictionaries(assoc. arrays), having hashes, are
efficient for storing sparse arrays


They are sparce arrays using hashing for lookup.


traversal of the dictionary looking for the proper key, and being much
less efficient if looking for the value and trying to retrieve its key.


Indeed, that's why dictionaries don't have a get key for
value operation.


But it also depends on the hash key and algorithm and how many spaces
are “available” for filling.


Yes, and Python's hashing has been tuned and optimised over many years.


I’ve not had much use of dictionaries in the past so maybe I am missing
something.


You are using them all the time. Python is built on dictionaries.
They are very powerful and efficient.


As I contemplated dictionary use, it seems changing the order
of entries is best left to double single arrays


There is no order. The order may change in use and you have
no control over that. It's a Python internal detail and you as a 
programmer cannot mess with it.



--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] yet another misunderstanding on my part

2014-10-22 Thread Alan Gauld

On 22/10/14 05:54, Clayton Kirkwood wrote:

__author__ = 'SYSTEM'


Its best not to invent your own dunder names.
You might run into a problem if a future Python release
decided to use the same name under the covers.


import string


Do you need this? Its very unusual these days
to use the string module.


#PricingDividends
raw_table = ('''
a: Asky: Dividend Yield
b: Bid d: Dividend per Share
b2: Ask (Realtime)   r1: Dividend Pay Date
b3: Bid (Realtime)q: Ex-Dividend Date
p: Previous Close
o: Open


Seems to be missing a closing ) ?

BTW the above would be a great place to use a dictionary,
its already almost in the right format...


import re, string


Keep imports together, it would make it easier to
see the duplication of string...


col_position, code, description = 0, [], []
key_name = raw_table.replace('\t','\n')

for each_line in  key_name.splitlines():
 if ':' in each_line:
code[col_position], description.append()  =
each_line.split(‘:’)   #neither works; first one is out of range


Where did 'code' come from?
You are trying to index into a non existent variable.
You need to declare the list and then use it.
The usual way to add items to a list is to use
the append() method.



 code[col_position] =  each_line.split(':')#why doesn’t


Again code is still undeclared.


code.append(c)


And even this won't work until you declare code to be a list.


I’ve seen an example of description.strip() work from a for in loop
assignment with out the can’t assign to function.


I can't quite parse that but I think you are looking at the wrong 
problem. Its not the strip() thats causing problems its the use

of code before declaring it.

code = []   # or code = list()  each declares code to be an empty list
code.append(item)   # this now adds an item to the list

If you want to use indexing to assign values then you need to assign 
dummy values to create the 'spaces' first. This is often done using a 
list comprehension:


# create a list of length size each containing zero
code = [0 for n in range(size)]

or cell multiplication

code = [0] * size


HTH
--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] yet another misunderstanding on my part

2014-10-22 Thread Steven D'Aprano
On Tue, Oct 21, 2014 at 09:54:49PM -0700, Clayton Kirkwood wrote:

> col_position, code, description = 0, [], []
> key_name = raw_table.replace('\t','\n')
> for each_line in key_name.splitlines():
> if ':' in each_line:
>code[col_position], description.append()  = each_line.split(':')
> #neither works; first one is out of range error, 2nd, can't assign to
> #function. I've used square brackets around various sections, and it doesn't
> like it

The trick to learning how to program is NOT to randomly make changes to 
your code and hope that you get lucky, but to understand why you are 
getting the errors you get.

Start here:

position = 0
codes = []
codes[position] = 999


This fails with an error:

IndexError: list assignment index out of range


What does that mean? It's an English sentence, a little bit terse but 
still understandable:

"list assignment index" -- what's that? It's the index used inside the 
square brackets, being used for list assignment. In this case, the index 
is 0.

"out of range" -- what's that mean? It tells you that the index you have 
provided (in this case, 0) is too big. Let's experiment to see what "too 
big" means:

py> alist = ['a', 'b', 'c']  # three items
py> alist[0] = 'A'
py> alist[1] = 'B'
py> alist[2] = 'C'
py> alist[3] = 'D'
Traceback (most recent call last):
  File "", line 1, in 
IndexError: list assignment index out of range


Aha! You can only assign to items in a list which already exist. In the 
experiment, I had a list with three items, item 0, item 1 and item 2, 
and assigning to index 0, 1 and 2 succeeded. But assigning to item 3 
(which doesn't exist) fails.

Go back to your list. It is an empty list, [], which means it has *no* 
items in it. Since there are no items in it, you cannot assign to any 
(non-existent) item.

If you can't assign to an item, since there aren't any, you have to 
append to the list.

I'm not sure where you got the idea of writing

description.append() = something


from. There's nothing in Python that I've ever seen that suggests that 
would work, and the error message should be clear:

py> x() = 23
  File "", line 1
SyntaxError: can't assign to function call


Try this instead:

py> descriptions = []
py> descriptions.append("something blue")
py> descriptions.append("something round")
py> descriptions.append("something flat")
py> print(descriptions)
['something blue', 'something round', 'something flat']


Like the name suggests, "append" appends something to the end of the 
list. So your code, which started like this:

# doesn't work
col_position, code, description = 0, [], []
key_name = raw_table.replace('\t','\n')
for each_line in key_name.splitlines():
if ':' in each_line:
code[col_position], description.append() = each_line.split(':')


could be written something like this:

# note plural names
codes, descriptions = [], []
key_name = raw_table.replace('\t','\n')
for each_line in key_name.splitlines():
if ':' in each_line:
code, description = each_line.split(':')
codes.append(code)
descriptions.append(description)


[...]
> What am I not seeing? I *do* spend hours trying different options, and study
> various documentation which confuse me and don't seem consistent.

It seems to me that you are probably failing to isolate the problem to 
*one* thing. When you get an error, you should ignore EVERYTHING else 
and just play around with that one function until you understand it. 
Open the interactive interpreter, and experiment, like I did above with 
the "alist[0]" assignments.


-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Passing Data to .DLL

2014-10-22 Thread eryksun
On Tue, Oct 21, 2014 at 7:04 PM, Wilson, Pete  wrote:
>
> ProcessIncomingSerialData_t = CFUNCTYPE(None, POINTER(c_uint8), c_uint16)
> process_incoming_serial_data = pt_dll.ProcessIncomingSerialData
> process_incoming_serial_data.argtypes = [ProcessIncomingSerialData_t]

ProcessIncomingSerialData takes two parameters: uint8_t *rx_buf and
uint16_t size.

process_incoming_serial_data.argtypes = [POINTER(c_uint8), c_uint16]
process_incoming_serial_data.restype = None

The buffer parameter isn't const, so pass a copy of string_buf.

size = len(string_buf)
rx_buf = (c_uint8 * size).from_buffer_copy(string_buf)
process_incoming_serial_data(rx_buf, size)

I'm going to meander off topic a bit to give you a warning...

Python strings are immutable by contract, so don't pass them directly
to C functions that might modify them. String immutability makes
interning possible, sometimes just locally in the code object and
sometimes globally in the interpreter. Here's an example of both in
CPython 2.7:

import abc
from ctypes import *

def test():
s = 'abc'
a = cast(s, POINTER(c_char * 3))[0]
a[:] = 'cba'
print 'abc'

>>> test.__code__.co_consts
(None, 'abc', 3, 0, 'cba')

Notice that the 2nd constant in co_consts is 'abc'. This gets stored
to s and later printed. In between I use ctypes to reverse it. So what
gets printed? If you guessed "cba", you're right.

>>> test()
cba

Look at the constants now:

>>> test.__code__.co_consts
(None, 'cba', 3, 0, 'cba')

So how about referencing the abc module?

>>> abc
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'abc' is not defined

OK, but do you think we can use cba instead?

>>> cba
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'cba' is not defined

This is yet another problem with mucking with the internal state of an
immutable object. Equal objects are supposed to hash the same.  'cba'
is now equal to the interned 'abc' string that I reversed, but it
probes to a different slot in the dict's hash table.

>>> test.__code__.co_consts[1] == 'cba'
True
>>> hash(test.__code__.co_consts[1]) == hash('cba')
False

OTOH, a new 'abc' string probes to the same slot in the hash table,
but it's no longer equal (i.e. it gets handled as a hash collision).

>>> test.__code__.co_consts[1] == 'abc'
False
>>> hash(test.__code__.co_consts[1]) == hash('abc')
True

This breaks dict lookup unless we use the interned string itself:.

>>> globals()[test.__code__.co_consts[1]]


So the moral is only pass Python strings to C functions that promise
(scout's honor) to not modify them. If the parameter isn't const, err
on the side of caution; copy the string to a ctypes buffer.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] A couple of somewhat esoteric questions

2014-10-22 Thread Steven D'Aprano
On Tue, Oct 21, 2014 at 04:54:33PM -0700, Clayton Kirkwood wrote:

> As I've contemplated the usage of dictionaries, I face the question of
> efficiency. Going back before most of you were probably born;<)) if I
> remember correctly dictionaries(assoc. arrays), having hashes, are efficient
> for storing sparse arrays with the added benefit of hiding the traversal of
> the dictionary looking for the proper key, and being much less efficient if
> looking for the value and trying to retrieve its key. But it also depends on
> the hash key and algorithm and how many spaces are "available" for filling.
> If a hash is created for a small array, which is known ahead of time with
> some possible hints, the array is efficient but has the distinct difficulty
> of use when more and more pairs are created, because either the new pair
> matches an already used hash point and a trail must be descended off of that
> particular hash point or a mechanism must be used to determine how the new
> pair should be stored elsewhere in the array like at the end and matching
> becomes time consuming. 

This is standard for hash tables. Python, if I recall correctly, uses 
linear addressing rather than chaining.

Python's hash function can return approximately 4294967296 different 
values (2**32), which means that for random or arbitrary keys, you won't 
expect more than a tiny handful of collisions. Of course a hostile 
adversary might, sometimes, be able to feed you keys that all hash the 
same, but in practice that's very unlikely to happen. And even if it 
does happen, the worst that will occur is that dict look-ups will 
degenerate to being proportional to the number of items, which isn't too 
bad.

> And/or, a new hash key and perhaps a different
> algorithm must be used for creating the larger array. 

Python always uses the same hash algorithm. It doesn't try to change 
algorithms as the table gets bigger, it just scales the hash value to 
the size of the table. As the table gets full, the table is doubled in 
size to make room.

(To be pedantic, I'm talking here about the standard CPython reference 
implementation. There are other implementations, such as Jython and 
IronPython and PyPy, which may do other things.)


> Also, since the array
> allows for multiple keys pointing to possibly identical values, the array is
> not necessarily 1 to 1 (could be 1 to multiple although we use replacement
> of the value normally) and definitely cannot be onto: there is no rule that
> says the mapping from value back to key is singular and unique.

Yes, but I don't see your point. Hash tables are designed to be 
one-to-many.

If you want to understand the *precise* details of how Python dicts 
work, you will need to read the source code written in C. But as an over 
simplification:

- when you create an empty dict, it is created with a certain number 
  of free slots in a table;
- as you add items to the dict, the dict knows how many free slots
  remain;
- when the table is half full, the dict resizes; very small dicts
  are increased to four times bigger, while larger dicts are 
  doubled in size;
- that means that *on average* adding new items to a dict takes
  the same amount of time (amortized over the lifetime of the
  dict).


> I've not had much use of dictionaries in the past so maybe I am missing
> something. As I contemplated dictionary use, it seems changing the order of
> entries is best left to double single arrays - which can be modified
> together when changing order. Dicts don't seem to support moving pairs
> around and in fact would be broken if changes were attempted.

I don't understand what you are trying to say here. Hash tables are 
unordered, and "changing the order of entries" makes no sense for them. 
Can you give a concrete example of what you're trying to do?


> Kind of like
> using a real dictionary, you can have a word (key) have multiple meanings
> (values),

In Python, the way to do that is by associating a list of meanings with 
the one key:

d = {'key': ['first', 'second', 'third'],
 'another key': ['alpha', 'beta']}


> and you can have multiple words (keys) having the same meaning
> (value). Again, with the difference from a real dictionary, our dicts can't
> have keys pointing to different values. 

They certainly can.


> But there are definitely uses for dicts.

One or two, one or two. Hundred. Thousand.

Seriously, dicts are probably the most commonly used data structure in 
Python, by far. They are used for modules, classes, instances, global 
variables are stored inside a dict, built-in functions are stored inside 
a dict, modules are cached inside a dict. They are efficient and fast 
and highly tuned, and there is almost never any need to try to re-invent 
the wheel.


-- 
Steven
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


[Tutor] Insert time into email...final code

2014-10-22 Thread Bo Morris
Just in case anyone else can benefit from this, here is my working code up
to this point

#!/usr/bin/python

import smtplib
from email.MIMEMultipart import MIMEMultipart
from email.MIMEText import MIMEText
from email.MIMEImage import MIMEImage
import time

strFrom = "HourlyReport.com"

strTo = "myem...@server.com"

t = time.strftime("%H:%M:%S  %m/%d/%y")

l = ['3102EHD-01108.png', '3102DHD-01109.png','3102EHD-01082.png',
'3102DHD-01033.png', '3102EHD-01302.png', '3102DHD-01149.png',
'3102EHD-01125.png', '3102DHD-01144.png', '3102EHD-01105.png']

msgRoot = MIMEMultipart('related')
msgRoot['Subject'] = 'Test Hourly Report'
msgRoot['From'] = strFrom
msgRoot['To'] = strTo
msgRoot.preamble = 'This is a multi-part message in MIME format.'

msgAlternative = MIMEMultipart('alternative')
msgRoot.attach(msgAlternative)

msgText = MIMEText('This is the alternative plain text message.')
msgAlternative.attach(msgText)

msgText = MIMEText('3102EHD-01108{time}3102DHD-01109{time}3102EHD-01082{time}3102DHD-01033{time}3102EHD-01302{time}3102DHD-01149{time}3102EHD-01125{time}3102DHD-01144{time}3102EHD-01105{time}'.format(time=t),
'html')

msgAlternative.attach(msgText)


for image in l:
with open(image, 'rb') as fh:
msgImage = MIMEImage(fh.read())
msgImage.add_header('Content-ID', '<{0}>'.format(image))
msgRoot.attach(msgImage)


try:
   smtpObj = smtplib.SMTP('localhost')
   smtpObj.sendmail(strFrom, strTo, msgRoot.as_string())
   print "Successfully sent email"
except smtplib.SMTPException:
   print "Error: unable to send email"
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Question on a select statement with ODBC

2014-10-22 Thread Al Bull

-Original Message-
From: Tutor [mailto:tutor-bounces+a.bull=pubdmgroup@python.org] On
Behalf Of Alan Gauld
Sent: Tuesday, October 21, 2014 6:42 PM
To: tutor@python.org
Subject: Re: [Tutor] Question on a select statement with ODBC

On 21/10/14 19:57, Al Bull wrote:

> have multiple records per ord_dbasub.  Is there a way I can structure 
> the select statement to retrieve only the most current record (based 
> on ord_date)?

Yes, the cursor can be told to only retrieve N records, in your case 1.

SELECT ord_dbasub, ord_pub,ord_date,ord_service,
...
FROM ord
WHERE ord_pub='QWKFIL'
ORDER BY ord_dbasub, ord_date
LIMIT 1

If the sort order is wrong you can specify ASC or DESC to reverse it as
needed.

> ord_rows = cursor.execute("select ord_dbasub, ord_pub, 
> ord_date,ord_service,"
>"ord_agency, ord_woa, ord_status,"
>"ord_channel, ord_source, ord_giftcomp,"
>"ord_cnreason "
>"from ord "
>"Where ord_pub='QWKFIL'"
>"order by ord_dbasub, ord_date").fetchall()

Rather than all those quotes you can use triple quotes:

ord_rows = cursor.execute('''select ord_dbasub, ord_pub,
  ord_date,ord_service,
  ord_agency, ord_woa, ord_status, etc...
  order by ord_dbasub, ord_date
  limit 1''').fetchall()
> for row in ord_rows:
> print (row.ord_dbasub, row.ord_date, row.ord_pub)
> # Add code here to find the most recent order per DBASUB and 
> delete other orders

If it's in order you could just access the first row using an index.

print (ord_rows[0])

> I have to admit that the concept of tuples & dictionaries has me a little
> bit confused.I'm used to working with arrays and arrays of structures.

tuples are just read-only lists, which, in turn, are arrays that can hold
any data type.

tuples are also like records without named fields. You can use a named tuple
from the collections module which is even more like a record.


-- 
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor
[Al Bull] 

I don't think I explained the problem properly. I have several hundred
thousand records in the ORD table.  There are many instances of records with
identical ORD_DBASUB values.   Where duplicates exist, I only want to keep
the most current record.   There could be 1-20 or more records with the same
ORD_DBASUB value.  I am close to having this working.   I added the
following statement:

ord_rows.reverse()

to reverse the order of the table.  Now for each ORD_DBASUB, the most
current record will be the first one.   I then added this code:

savedbasub = 0
for row in ord_rows:
   if savedbasub == row.ord_dbasub:
   ord_rows.remove(row)
   delcount += 1  
   else:
  savedbasub = row.ord_dbasub

This code works except in very specific cases.  Take the following example:
 ORD_DBASUB DATE
1) 10360 2004-11-02 
2) 10360 2004-09-03 
3) 10334 2004-04-05 
4) 10334 2004-03-08 

Record #1 is saved, as it should be.   Record #2 is correctly removed.
Record #3 is correctly saved, but record #4 is not removed.It appears
that ROW is being moved to the next entry after the ord_rows.remove
statement, then being moved again at the top of the loop causing me to drop
down into the else clause for record #4.

Al Bull, Chief Technology Officer/Owner
Publishers Data Management Group


a.b...@pubdmgroup.com
815-732-5297

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Question on a select statement with ODBC

2014-10-22 Thread Alan Gauld

On 22/10/14 16:06, Al Bull wrote:

I don't think I explained the problem properly. I have several hundred
thousand records in the ORD table.  There are many instances of records with
identical ORD_DBASUB values.   Where duplicates exist, I only want to keep
the most current record.


Ah, OK thats very different.
You can do it in SQL but it gets messy and depends on the details of the 
ODBC SQL, which I don't know... It would involve a nested select

with an inner join I suspect.


This code works except in very specific cases.  Take the following example:
  ORD_DBASUB DATE
1) 10360 2004-11-02
2) 10360 2004-09-03
3) 10334 2004-04-05
4) 10334 2004-03-08

Record #3 is correctly saved, but record #4 is not removed.It appears
that ROW is being moved to the next entry after the ord_rows.remove


That's correct you should never modify the collection that you are 
iterating over with a for loop.


Instead convert to using a while loop and only increment the index
if you don't remove an thing.

Alternatively make a copy of the collection and iterate over that,
but a while is usually preferable IMHO.

--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python sqlite3 issue

2014-10-22 Thread Juan Christian
So guys, now I have this code that is fully working:

import sqlite3

db = sqlite3.connect('db.sqlite')


def ini_db():
db.execute('''
CREATE TABLE IF NOT EXISTS TOPICS(
ID INTEGER NOT NULL,
URL VARCHAR NOT NULL,
AUTHOR VARCHAR NOT NULL,
MESSAGE VARCHAR NOT NULL
);
''')


def insert_db(_id, url, author, message):
db.execute("INSERT INTO TOPICS (ID, URL, AUTHOR, MESSAGE) VALUES (?, ?,
?, ?)", (_id, url, author, message))
db.commit()


def get_db(_id):
cursor = db.execute("SELECT ID, URL, AUTHOR, MESSAGE FROM TOPICS WHERE
ID = ?", (_id,))
return cursor.fetchone()


if __name__ == '__main__':
ini_db()

insert_db(12, 'abc.com', 'a', 'b')
insert_db(20, 'abc2.com', 'a2', 'c')
insert_db(1, 'abc3.com', 'a3', 'd')

for row in db.execute('SELECT * FROM TOPICS ORDER BY ID'):
print(row)

db.close()


--

Anything else that I need to improve/change? Regarding the 'DROP TABLE'
before creating, It wouldn't be good for me, because I do want the 'old'
data from the table there, I don't want to drop them!
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] A couple of somewhat esoteric questions

2014-10-22 Thread Clayton Kirkwood


!-Original Message-
!From: Tutor [mailto:tutor-bounces+crk=godblessthe...@python.org] On
!Behalf Of Steven D'Aprano
!Sent: Wednesday, October 22, 2014 4:40 AM
!To: tutor@python.org
!Subject: Re: [Tutor] A couple of somewhat esoteric questions
!
!On Tue, Oct 21, 2014 at 04:54:33PM -0700, Clayton Kirkwood wrote:
!
!> As I've contemplated the usage of dictionaries, I face the question of
!> efficiency. Going back before most of you were probably born;<)) if I
!> remember correctly dictionaries(assoc. arrays), having hashes, are
!> efficient for storing sparse arrays with the added benefit of hiding
!> the traversal of the dictionary looking for the proper key, and being
!> much less efficient if looking for the value and trying to retrieve
!> its key. But it also depends on the hash key and algorithm and how
!many spaces are "available" for filling.
!> If a hash is created for a small array, which is known ahead of time
!> with some possible hints, the array is efficient but has the distinct
!> difficulty of use when more and more pairs are created, because either
!> the new pair matches an already used hash point and a trail must be
!> descended off of that particular hash point or a mechanism must be
!> used to determine how the new pair should be stored elsewhere in the
!> array like at the end and matching becomes time consuming.
!
!This is standard for hash tables. Python, if I recall correctly, uses
!linear addressing rather than chaining.
!
!Python's hash function can return approximately 4294967296 different
!values (2**32), which means that for random or arbitrary keys, you won't
!expect more than a tiny handful of collisions. Of course a hostile
!adversary might, sometimes, be able to feed you keys that all hash the
!same, but in practice that's very unlikely to happen. And even if it
!does happen, the worst that will occur is that dict look-ups will
!degenerate to being proportional to the number of items, which isn't too
!bad.


I would hope that the full array is not created?


!
!> And/or, a new hash key and perhaps a different algorithm must be used
!> for creating the larger array.
!
!Python always uses the same hash algorithm. It doesn't try to change
!algorithms as the table gets bigger, it just scales the hash value to
!the size of the table. As the table gets full, the table is doubled in
!size to make room.

Out of curiousity, does a new array get built in a larger home and
everything redistributed, or does more memory get added on? I think the
second would be difficult because a new seed and size value would be needed
to properly distribute.

!
!(To be pedantic, I'm talking here about the standard CPython reference
!implementation. There are other implementations, such as Jython and
!IronPython and PyPy, which may do other things.)
!
!
!> Also, since the array
!> allows for multiple keys pointing to possibly identical values, the
!> array is not necessarily 1 to 1 (could be 1 to multiple although we
!> use replacement of the value normally) and definitely cannot be onto:
!> there is no rule that says the mapping from value back to key is
!singular and unique.
!
!Yes, but I don't see your point. Hash tables are designed to be one-to-
!many.

For clarification, a key only has one value which can be changed. Multiple
keys can have the same value (hopefully not to the same memory location,
because one would usually not want the change of one key's value to alter
another key's value. As to the hash table, yes, I agree that this would be
one to many, hence the chains.

!
!If you want to understand the *precise* details of how Python dicts
!work, you will need to read the source code written in C. But as an over
!simplification:
!
!- when you create an empty dict, it is created with a certain number
!  of free slots in a table;
!- as you add items to the dict, the dict knows how many free slots
!  remain;
!- when the table is half full, the dict resizes; very small dicts
!  are increased to four times bigger, while larger dicts are
!  doubled in size;
!- that means that *on average* adding new items to a dict takes
!  the same amount of time (amortized over the lifetime of the
!  dict).
!
!
!> I've not had much use of dictionaries in the past so maybe I am
!> missing something. As I contemplated dictionary use, it seems changing
!> the order of entries is best left to double single arrays - which can
!> be modified together when changing order. Dicts don't seem to support
!> moving pairs around and in fact would be broken if changes were
!attempted.
!
!I don't understand what you are trying to say here. Hash tables are
!unordered, and "changing the order of entries" makes no sense for them.
!Can you give a concrete example of what you're trying to do?

The changing of the order is necessary when you want numeric indexing, say
for columns or rows.

!
!
!> Kind of like
!> using a real dictionary, you can have a word (key) have multiple
!meanings
!> (values),
!
!In Python, the way to do 

Re: [Tutor] Python sqlite3 issue

2014-10-22 Thread Alan Gauld

On 22/10/14 18:38, Juan Christian wrote:


def ini_db():
 db.execute('''
 CREATE TABLE IF NOT EXISTS TOPICS(
 ID INTEGER NOT NULL,
 URL VARCHAR NOT NULL,
 AUTHOR VARCHAR NOT NULL,
 MESSAGE VARCHAR NOT NULL
 );
 ''')


So you no longer have a primary key. You are taking on management
of uniqueness yourself. That's OK provided you understand fully the 
consequences of that decision.


Incidentally you don't need the semi-colon inside the execute. It can 
only execute the entire string so if there's only one command you

don't need the terminator.


def insert_db(_id, url, author, message):
 db.execute("INSERT INTO TOPICS (ID, URL, AUTHOR, MESSAGE) VALUES
(?, ?, ?, ?)", (_id, url, author, message))
 db.commit()


Note that this makes no checks for unique ID so you put the onus
on the inserting code to provide a unique ID.


def get_db(_id):
 cursor = db.execute("SELECT ID, URL, AUTHOR, MESSAGE FROM TOPICS
WHERE ID = ?", (_id,))
 return cursor.fetchone()


What happens if there are multiple rows returned (non unique IDs)?
You only get the first (and SQL does not guarantee order so it might
be a different one each time...), is that sufficient?



if __name__ == '__main__':
 ini_db()

 insert_db(12, 'abc.com ', 'a', 'b')
 insert_db(20, 'abc2.com ', 'a2', 'c')
 insert_db(1, 'abc3.com ', 'a3', 'd')

 for row in db.execute('SELECT * FROM TOPICS ORDER BY ID'):
 print(row)

 db.close()


--

Anything else that I need to improve/change? Regarding the 'DROP TABLE'
before creating, It wouldn't be good for me, because I do want the 'old'
data from the table there, I don't want to drop them!


That's fine but if you ever try to change the structure of your table 
(other than adding a column to the end) you will have to recreate the 
table; which you won't be able to do without dropping it first. (You can 
rename the original however and then copy the data from it to the new 
table, before dropping the renamed version.)


Finally, in production code you should not use select *. Always provide 
the field names in the order you want them. That's because if somebody 
else adds columns or changes their order (not likely in SQLite but 
common in other DBs) your select will not be broken.


--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Insert time into email

2014-10-22 Thread Albert-Jan Roskam


On Mon, Oct 20, 2014 6:02 PM CEST Chris “Kwpolska” Warrick wrote:

>On Mon, Oct 20, 2014 at 2:34 PM, Bo Morris  wrote:
>> hello all, hope everyone is doing well.
>>
>> The below code works, however I am going back and trying to enter the time
>> and date and I cant quite figure out how to do this without breaking the
>> code.
>>
>> #!/usr/bin/python
>>
>> import smtplib
>> from email.MIMEMultipart import MIMEMultipart
>> from email.MIMEText import MIMEText
>> from email.MIMEImage import MIMEImage
>> import time
>>
>> strFrom = "HourlyReport.com"
>
>PS. You may want to use a real e-mail address here.  Or, at the very
>least, something that looks like one.
>
>> #strTo = "engineer...@oneconnxt.com"
>> #strTo = "mmed...@onemediacorpinc.com"
>> strTo = "b...@onemediacorpinc.com"
>>
>> l = ['3102EHD-01108.png', '3102DHD-01109.png','3102EHD-01082.png',
>> '3102DHD-01033.png', '3102EHD-01302.png', '3102DHD-01149.png',
>> '3102EHD-01125.png', '3102DHD-01144.png', '3102EHD-01105.png']
>>
>> t = time.strftime("%H:%M:%S")
>> d = time.strftime("%d/%m/%Y")
>>
>> msgRoot = MIMEMultipart('related')
>> msgRoot['Subject'] = 'Test Hourly Report'
>> msgRoot['From'] = strFrom
>> msgRoot['To'] = strTo
>> msgRoot.preamble = 'This is a multi-part message in MIME format.'
>>

Shouldn't date be specified too? msgRoot['Date'] = datetime...
The other day I forgot to do this and the date was Jan 1970 iirc (Linux, I have 
never seen it on Windows)
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python sqlite3 issue

2014-10-22 Thread Juan Christian
On Wed, Oct 22, 2014 at 4:37 PM, Alan Gauld 
wrote:
>
> Incidentally you don't need the semi-colon inside the execute. It can only
> execute the entire string so if there's only one command you
> don't need the terminator.


Ok, thanks!


Note that this makes no checks for unique ID so you put the onus
> on the inserting code to provide a unique ID.
>
> What happens if there are multiple rows returned (non unique IDs)?
> You only get the first (and SQL does not guarantee order so it might
> be a different one each time...), is that sufficient?
>

I'll get this id from here (http://steamcommunity.com/app/440/tradingforum/),
every topic has a unique ID.


That's fine but if you ever try to change the structure of your table
> (other than adding a column to the end) you will have to recreate the
> table; which you won't be able to do without dropping it first. (You can
> rename the original however and then copy the data from it to the new
> table, before dropping the renamed version.)
>

I won't need to change the structure, but if I do, I can DROP the table, no
problem with that.


Finally, in production code you should not use select *. Always provide the
> field names in the order you want them. That's because if somebody else
> adds columns or changes their order (not likely in SQLite but common in
> other DBs) your select will not be broken.


Ok, thanks!


NEW CODE:

import sqlite3

db = sqlite3.connect('db.sqlite')


def ini_db():
db.execute('''CREATE TABLE IF NOT EXISTS TOPICS (
ID INTEGER NOT NULL,
URL VARCHAR NOT NULL,
AUTHOR VARCHAR NOT NULL,
MESSAGE VARCHAR NOT NULL
)'''
)


def insert(topic_id, url, author, message):
db.execute("INSERT INTO TOPICS (ID, URL, AUTHOR, MESSAGE) VALUES (?, ?,
?, ?)", (topic_id, url, author, message))
db.commit()


def get(topic_id):
cursor = db.execute("SELECT ID, URL, AUTHOR, MESSAGE FROM TOPICS WHERE
ID = ?", (topic_id,))
return cursor.fetchone()


if __name__ == '__main__':
ini_db()

insert(12, 'abc.com', 'a', 'b')
insert(20, 'abc2.com', 'a2', 'c')
insert(1, 'abc3.com', 'a3', 'd')

for row in db.execute('SELECT ID, URL, AUTHOR, MESSAGE FROM TOPICS'):
print(row)

db.close()


The only thing left now is that the topics in this forum has a one/two
weeks lifespan, and I think Steam reuses the same ID for new topics that
was used in, lets say a 1 month-old topic (already closed and gone for
weeks), I don't know for sure, but their Inventory/User API is a mess in
some parts, so I don't trust them in this matter either. How would be a
good approach regarding that? Use UPDATE? Use if-else?
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Passing Data to .DLL

2014-10-22 Thread eryksun
On Wed, Oct 22, 2014 at 3:50 PM, Wilson, Pete  wrote:
> I don't understand the line
> rx_buf = (c_uint8 * rx_buf_size).from_buffer_copy(string_buf)

A buffer is a block of memory used to pass data between functions,
processes, or systems. Specifically its use as a 'buffer' comes from
using a block of memory to buffer I/O operations. There are also
buffers implemented in hardware. They're typically FIFO (first in,
first out) queues or circular buffers (e.g. the sample buffer in an
ADC).

In ctypes, the expression `c_uint8 * rx_buf_size` creates an array
type that consists of rx_buf_size elements of type c_uint8. Note that
an array in C is an aggregate type. It's not a pointer, even though it
degenerates to a pointer to the first element when passed as an
argument to a function (look back at how I defined it in
process_incoming_serial_data.argtypes).

An instance of this array type has a contiguous buffer that consists
of rx_buf_size elements that are each sizeof(c_uint8) bytes:

>>> rx_buf_size = 8
>>> rx_buf_t = c_uint8 * rx_buf_size
>>> sizeof(c_uint8) * 8
8
>>> sizeof(rx_buf_t)
8

> or where .from_buffer_copy() came from but it works...

from_buffer is a class method of ctypes data types. It creates an
instance that shares the same base address as the target buffer, but
only if it's writable and at least the same size. In this case
'buffer' is referring to Python's buffer protocol. Python byte strings
implement this protocol, but not unicode strings.

Immutable strings are read-only buffers:

>>> rx_buf_t.from_buffer('01234567')[:]
Traceback (most recent call last):
  File "", line 1, in 
TypeError: Cannot use string as modifiable buffer

A bytearray is writable:

>>> string_buf = bytearray('01234567')
>>> rx_buf = rx_buf_t.from_buffer(string_buf)
>>> rx_buf[:]
[48, 49, 50, 51, 52, 53, 54, 55]

Note that the buffer is shared by the bytearray and ctypes array:

>>> string_buf[0] = '7'
>>> rx_buf[:]
[55, 49, 50, 51, 52, 53, 54, 55]

from_buffer_copy is similar, accept instead of sharing the buffer it
makes a private copy. Thus you can use it with an immutable string:

>>> string_buf = '01234567'
>>> rx_buf = rx_buf_t.from_buffer_copy(string_buf)
>>> rx_buf[:]
[48, 49, 50, 51, 52, 53, 54, 55]

In this case the buffer is *not* shared:

>>> rx_buf[0] = ord('7')
>>> string_buf
'01234567'

These class methods are implemented by the metaclass, PyCArrayType.

>>> PyCArrayType = type(rx_buf_t)
>>> PyCArrayType


>>> print '\n'.join(sorted(vars(PyCArrayType)))
__doc__
__mul__
__new__
__rmul__
from_address
from_buffer
from_buffer_copy
from_param
in_dll

from_address is particularly dangerous. Misusing it will probably
crash the interpreter.

in_dll gives you access to a library's data exports. For example, the
flag Py_HashRandomizationFlag indicates whether the interpreter is
randomizing string hashes (command-line option -R). In Python 3 it's
on by default:

>>> sys.flags.hash_randomization
1
>>> c_int.in_dll(pythonapi, 'Py_HashRandomizationFlag')
c_long(1)

> I promise I will not knowingly pass Python strings to C.

It's fine if you see something such as `const char *var` in the
function prototype. The const qualifier lets you know the function
promises to not modify the buffer. In C, a promise is the best you can
get. Better still the docs will tell you whether or not the buffer
needs to be writable. This is an important distinction to make for the
shared library itself. A memory block could literally be read only
(not just by contract), such that trying to write to it will raise a
Windows access violation or POSIX segfault.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Python sqlite3 issue

2014-10-22 Thread Alan Gauld

On 22/10/14 23:30, Juan Christian wrote:


The only thing left now is that the topics in this forum has a one/two
weeks lifespan, and I think Steam reuses the same ID for new topics that
was used in, lets say a 1 month-old topic


In that case I'd go back to using a primary key ID set by SQLite and 
have a specific field for SteamID. Then you can have multiple Steam IDs 
but still have a unique ID for your records.


You might need a date field as well to distinguish/sort the various 
topics with similar IDs.



--
Alan G
Author of the Learn to Program web site
http://www.alan-g.me.uk/
http://www.flickr.com/photos/alangauldphotos

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] A couple of somewhat esoteric questions

2014-10-22 Thread Dave Angel
"Clayton Kirkwood"  Wrote in message:
> 
> 
> !-Original Message-
> !From: Tutor [mailto:tutor-bounces+crk=godblessthe...@python.org] On
> !Behalf Of Steven D'Aprano
...
> 
> For clarification, a key only has one value which can be changed. 

No, because the key has to be immutable, like a string or an int.

> Multiple
> keys can have the same value (hopefully not to the same memory location,
> because one would usually not want the change of one key's value to alter
> another key's value. As to the hash table, yes, I agree that this would be
> one to many, hence the chains.

Memory locations are an implementation detail. We're talking in
 this paragraph about keys and values. A value is an object, the
 dict provides a one-way mapping from immutable key to an
 arbitrary value object. If the value objects happen to be
 immutable,  it makes no difference if a program uses the same
 value for multiple keys. If the values are not immutable,  python
 makes no assurance whether two values are equal, or identical. If
 the latter is undesirable for a particular use, it's up to the
 application logic to prevent it. It's probably more often useful
 than problematic. Python makes no such assurances.
 




> !Can you give a concrete example of what you're trying to do?
> 
> The changing of the order is necessary when you want numeric indexing, say
> for columns or rows.
> 

No idea how this relates to dicts, which have no order, nor rows
 nor columns. Make it concrete.


-- 
DaveA

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] Passing Data to .DLL

2014-10-22 Thread eryksun
On Wed, Oct 22, 2014 at 6:05 PM, eryksun  wrote:
> from_buffer_copy is similar, accept instead of sharing the buffer

That should be ex-cept (conjunction for an exception clause), not
ac-cept (verb, to receive). I missed that in my initial proofread. It
takes a while to clear my mental buffer enough for a fresh look.
___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor


Re: [Tutor] A couple of somewhat esoteric questions

2014-10-22 Thread Dave Angel
Dave Angel  Wrote
 in message:
> "Clayton Kirkwood"  Wrote in message:
>> 
>> 
>> !-Original Message-
>> !From: Tutor [mailto:tutor-bounces+crk=godblessthe...@python.org] On
>> !Behalf Of Steven D'Aprano
> ...
>> 
>> For clarification, a key only has one value which can be changed. 
> 
> No, because the key has to be immutable, like a string or an int.

My error for reading your statement wrong.

> 
>> Multiple
>> keys can have the same value (hopefully not to the same memory location,
>> because one would usually not want the change of one key's value to alter
>> another key's value. As to the hash table, yes, I agree that this would be
>> one to many, hence the chains.
> 
> Memory locations are an implementation detail. We're talking in
>  this paragraph about keys and values. A value is an object, the
>  dict provides a one-way mapping from immutable key to an
>  arbitrary value object. If the value objects happen to be
>  immutable,  it makes no difference if a program uses the same
>  value for multiple keys. If the values are not immutable,  python
>  makes no assurance whether two values are equal, or identical. If
>  the latter is undesirable for a particular use, it's up to the
>  application logic to prevent it. It's probably more often useful
>  than problematic. Python makes no such assurances.
>  
> 
> 
> 
> 
>> !Can you give a concrete example of what you're trying to do?
>> 
>> The changing of the order is necessary when you want numeric indexing, say
>> for columns or rows.
>> 
> 
> No idea how this relates to dicts, which have no order, nor rows
>  nor columns. Make it concrete.
> 
> 
> -- 
> DaveA
> 
> ___
> Tutor maillist  -  Tutor@python.org
> To unsubscribe or change subscription options:
> https://mail.python.org/mailman/listinfo/tutor
> 
> 


-- 
DaveA

___
Tutor maillist  -  Tutor@python.org
To unsubscribe or change subscription options:
https://mail.python.org/mailman/listinfo/tutor