From breamoreboy at yahoo.co.uk Wed Apr 1 01:19:16 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 01 Apr 2015 00:19:16 +0100 Subject: [Tutor] Unexpected results using enumerate() and .split() In-Reply-To: References: Message-ID: On 31/03/2015 21:49, boB Stepp wrote: > On Tue, Mar 31, 2015 at 3:42 PM, Zachary Ware > wrote: > >> Also, not that since you aren't using the index for anything, you >> don't need to use enumerate() to iterate over the list. Just do "for >> item in L:". Of course, if you actually use the index in the real >> code that I assume this was cut out of, keep enumerate; it's the right >> tool for the job. > > Yeah, I simplified my actual code into the smallest snippet that I > could reproduce my problem in. My actual code need the index. > Using an index is perhaps the traditional way of doing things but there are other options. As an example you might like to see the pairwise function here http://pythonhosted.org//more-itertools/api.html with the code available on pypi if you'd like to play. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From mccombs at imperium.org Wed Apr 1 03:39:45 2015 From: mccombs at imperium.org (P McCombs) Date: Tue, 31 Mar 2015 18:39:45 -0700 Subject: [Tutor] ArcGIS Create a python script to generate north-facing aspect raster from digital elevation model In-Reply-To: <1426921551.78493.YahooMailBasic@web161005.mail.bf1.yahoo.com> References: <1426921551.78493.YahooMailBasic@web161005.mail.bf1.yahoo.com> Message-ID: On Mar 21, 2015 1:22 AM, "Michael Omohundro" wrote: > > Does anyone know how to create a python script to generate an aspect raster from the input elevation in a digital elevation model? > This topic is out of the normal scope of the mailing list. It's hard to say if you are having a python issue or an ArcGIS issue. I could possibly help with the latter, but please provide the trace back you get when it errors out, or how the output differs from what you expect. Without the data you are using I'm not going to attempt to run your code. > > I need to specify TWO variables as user parameters: input elevation and output north-facing aspect. > I need to create an aspect raster from the input elevation from a digital elevation model. > I need to find the north facing aspect is the trick, between 0 and 22.5 and between 337.5 ? 360. These are the north facing elevation ranges. > I need to reclass the north facing aspect into a 1/Nodata raster. > Any cell is north facing should have value 0, other cells should be NoData. > I need to save the results as a permanent raster named as my second input parameter. > I can't use ModelBuilder then convert it into Python script. > > Here is what I have so far: > > > # Created on: March 20 2015 > # Usage: lab03-5 Aspect from raster surface > # Requirements: ArcGIS Desktop and Spatial Analyst Extension > # --------------------------------------------------------------------------- > > # Import system modules > import arcpy > from arcpy import env > from arcpy.sa import * In my experience this makes debugging harder, I can't tell if you are using local functions or module functions without a detailed knowledge of the module you imported. > arcpy.env.overwriteOutput = True > > # Set environment settings. dem30 is the digital elevation model that holds the elevation data. > elevation = r"F:\NW_Missouri_State_University\_Python_Class\Week_10\lab10\dem30" > > # North facing elevation 1, range 0 to 22.5 > inRange_North1 = range (0, 22.5, 0.5) > #North facing elevation 2,range 337.5 - 360 > inRange_North2 = range (337.5, 360, 0.5) > > # Set local variables > inRaster = "elevation" > > # Check out the ArcGIS Spatial Analyst extension license > arcpy.CheckOutExtension("Spatial") > > # Execute Aspect > outAspect = Aspect(inRaster) > > # Save the output > outAspect.save("F:\NW_Missouri_State_University\_Python_Class\Week_10\lab10\TestLab10_5") > > # Specify the current workspace as the workspace where the input elevation raster is. > # Extract the base name of the elevation raster. > arcpy.env.workspace = os.path.dirname(elevation) > inputElev = os.path.basename(elevation) > > # Specify the output raster name as the input elevation name appending with ?NorthFacing?. > saveReclass = arcpy.env.workspace + os.sep + inputElev + "NorthFacing" > > # Check out the Spatial Analyst extension license for the script. > arcpy.CheckOutExtension("Spatial") > > # Construct a map algebra expression to find the cell with elevation equal to the range values. > minRaster = arcpy.sa.Raster(inputElev) = inRange_North1 > maxRaster = arcpy.sa.Raster(inputElev) = inRange_North2 > > # Construct a map algebra expression to perform a Boolean And > # operation on the cell values of minRaster and maxRaster. > # If the cell value is 1 in both raster, then set the output cell value as 1. > # Otherwise, set the output cell value as 0. Save the output raster as variable outRaster. > outRaster = minRaster & maxRaster > > # Create a remap object through RemapValue() function. > # If the old value is 0, then set the new value as NODATA. > # If the old value is 1, then set the new value as 1. > > remap = arcpy.sa.RemapValue([[0, "NODATA"], [1, 1]]) > outReclassify = arcpy.sa.Reclassify( > outRaster, "Value", remap, "NODATA") > > #Call the save method on the raster object to save the raster as permanent dataset. > outReclassify.save(saveReclass) > > # Check in the Spatial Analyst extension license. > arcpy.CheckInExtension("Spatial") > I'm guessing that you've resolved this problem in the past week, but for future problems I encourage you to check what data types are expected for the functions you are calling. They can be unexpected sometimes in arcpy. Paul McCombs From cybervigilante at gmail.com Wed Apr 1 06:50:43 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Tue, 31 Mar 2015 21:50:43 -0700 Subject: [Tutor] Python Idioms? Message-ID: I'm looking at this and can't see how it works, although I understand zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean it works in a special way so I can't figure it out from basic principles? It looks to me like the iterator in the list gets doubled, so the zip should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] What am I missing here? >>> s = [1,2,3,4,5,6,7,8] >>> list(zip(*[iter(s)]*2)) >>> [(1, 2), (3, 4), (5, 6), (7, 8)] https://docs.python.org/3/library/functions.html#zip -- Jim From alan.gauld at btinternet.com Wed Apr 1 11:04:15 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 01 Apr 2015 10:04:15 +0100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: On 01/04/15 05:50, Jim Mooney wrote: > I'm looking at this and can't see how it works, although I understand > zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean > it works in a special way so I can't figure it out from basic principles? No idiom means a common pattern of usage in the community. In this case thats true of zip(), its less true of this case which is somewhat obscure. > It looks to me like the iterator in the list gets doubled, so the zip > should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] > > What am I missing here? The fact that thew list contains a reference to an iterator so when you multiply by two you get two references to *the same* iterator. So each time the iterator gets accessed it returns the next number in the sequence, not the same number twice. >>>> s = [1,2,3,4,5,6,7,8] >>>> list(zip(*[iter(s)]*2)) >>>> [(1, 2), (3, 4), (5, 6), (7, 8)] Personally I'd have used slicing in this example: zip(s[::2],s[1::2]) Is that any clearer? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From wolfgang.maier at biologie.uni-freiburg.de Wed Apr 1 12:04:34 2015 From: wolfgang.maier at biologie.uni-freiburg.de (Wolfgang Maier) Date: Wed, 01 Apr 2015 12:04:34 +0200 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: On 04/01/2015 11:04 AM, Alan Gauld wrote: > On 01/04/15 05:50, Jim Mooney wrote: > >>>>> s = [1,2,3,4,5,6,7,8] >>>>> list(zip(*[iter(s)]*2)) >>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] > > Personally I'd have used slicing in this example: > > zip(s[::2],s[1::2]) > With an emphasis on *in this example*. The idiom you are citing works on any iterable, not all of which support slicing and the slicing version requires two passes over the data. From alan.gauld at btinternet.com Wed Apr 1 12:50:11 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 01 Apr 2015 11:50:11 +0100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: On 01/04/15 11:04, Wolfgang Maier wrote: > On 04/01/2015 11:04 AM, Alan Gauld wrote: >> On 01/04/15 05:50, Jim Mooney wrote: >> >>>>>> s = [1,2,3,4,5,6,7,8] >>>>>> list(zip(*[iter(s)]*2)) >>>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] >> >> Personally I'd have used slicing in this example: >> >> zip(s[::2],s[1::2]) >> > > With an emphasis on *in this example*. > > The idiom you are citing works on any iterable, not all of which support > slicing and the slicing version requires two passes over the data. Agreed, but readability always trumps performance, unless performance is critical. In which case readability usually trumps performance. And especially on a beginners list. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From breamoreboy at yahoo.co.uk Wed Apr 1 13:06:33 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 01 Apr 2015 12:06:33 +0100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: On 01/04/2015 11:50, Alan Gauld wrote: > On 01/04/15 11:04, Wolfgang Maier wrote: >> On 04/01/2015 11:04 AM, Alan Gauld wrote: >>> On 01/04/15 05:50, Jim Mooney wrote: >>> >>>>>>> s = [1,2,3,4,5,6,7,8] >>>>>>> list(zip(*[iter(s)]*2)) >>>>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] >>> >>> Personally I'd have used slicing in this example: >>> >>> zip(s[::2],s[1::2]) >>> >> >> With an emphasis on *in this example*. >> >> The idiom you are citing works on any iterable, not all of which support >> slicing and the slicing version requires two passes over the data. > > Agreed, but readability always trumps performance, > unless performance is critical. > In which case readability usually trumps performance. > > And especially on a beginners list. > In which case I'll stick with the more-itertools pairwise() function which I pointed out on another thread just yesterday. From http://pythonhosted.org//more-itertools/api.html Returns an iterator of paired items, overlapping, from the original >>> take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From davea at davea.name Wed Apr 1 14:45:44 2015 From: davea at davea.name (Dave Angel) Date: Wed, 01 Apr 2015 08:45:44 -0400 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: <551BE878.7070901@davea.name> On 04/01/2015 12:50 AM, Jim Mooney wrote: > I'm looking at this and can't see how it works, although I understand > zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean > it works in a special way so I can't figure it out from basic principles? > It looks to me like the iterator in the list gets doubled, so the zip > should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] > > What am I missing here? > >>>> s = [1,2,3,4,5,6,7,8] >>>> list(zip(*[iter(s)]*2)) >>>> [(1, 2), (3, 4), (5, 6), (7, 8)] > > https://docs.python.org/3/library/functions.html#zip > In that same thread, Peter Otten posted the following, which I think is probably a bit clearer: >>> flat_pairs = ['broadcast', '"d8on"', 'broadcast', '"d11on"'] >>> it = iter(flat_pairs) >>> pairs = list(zip(it, it)) >>> pairs That does exactly the same thing, but in the first one you can replace the '2' with a variable, to make variable sized tuples. In both cases, the trick is that the same iterator is used twice in the expression, so even though zip is taking one from each, there are no duplications. If you know the original data is a list, or at least that it can do slices, then you can do Alan's suggestion: zip(s[::2],s[1::2]) Or you could try: from itertools import islice pairs = zip(islice(s, 0, 9999, 2), islice(s, 1, 9999, 2)) -- DaveA From steve at pearwood.info Wed Apr 1 15:01:44 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 2 Apr 2015 00:01:44 +1100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: <20150401130143.GT25453@ando.pearwood.info> On Tue, Mar 31, 2015 at 09:50:43PM -0700, Jim Mooney wrote: > I'm looking at this and can't see how it works, although I understand > zipping and unpacking. The docs say it's a Python idiom. Does "idiom" mean > it works in a special way so I can't figure it out from basic principles? > It looks to me like the iterator in the list gets doubled, so the zip > should make it [(1,1),(2,2),(3,3),... ], not [(1,2),(3,4),...] > > What am I missing here? The secret is that list multiplication doesn't make *copies*, it replicates multiple references to the same object. > >>> s = [1,2,3,4,5,6,7,8] > >>> list(zip(*[iter(s)]*2)) > >>> [(1, 2), (3, 4), (5, 6), (7, 8)] Let's pull this apart and see how it ticks. It may actually be more obvious what is going on if we use more than two references, and do by hand what * does for us above. py> s = [100, 200, 300, 400, 500, 600, 700, 800, 900] py> it = iter(s) # One iterator object. py> next(it), next(it), next(it) # Call next three times. (100, 200, 300) py> args = [it, it, it] # Like [it]*3 py> for x in args: ... print(next(x)) # Like next(it). ... 400 500 600 We created *one* iterator. First we called next(it) three times, by hand, which yields the first three items in the list s. Then we stick the iterator in a new list three times, and loop over that, calling next() each time. That is equivalent to next(it) three more times, which gives us the next three items. Finally, we pass them to zip(), as separate arguments: py> list(zip(*args)) [(700, 800, 900)] Which gives us the next three items. At that point, we run out of items, and zip completes. Putting it (almost) all together now. Remember that `it` above, the iterator, is now exhausted. It has walked all the way through list s, so we need a new iterator to make it work again: py> list(it) # it is exhausted. [] py> it = iter(s) # So re-create it. py> list(zip(*[it]*3)) [(100, 200, 300), (400, 500, 600), (700, 800, 900)] We can avoid the temporary variable: py> list(zip(*[iter(s)]*3)) [(100, 200, 300), (400, 500, 600), (700, 800, 900)] -- Steve From steve at pearwood.info Wed Apr 1 15:16:30 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 2 Apr 2015 00:16:30 +1100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: <20150401131630.GU25453@ando.pearwood.info> On Wed, Apr 01, 2015 at 12:06:33PM +0100, Mark Lawrence wrote: > In which case I'll stick with the more-itertools pairwise() function > which I pointed out on another thread just yesterday. From > http://pythonhosted.org//more-itertools/api.html > > > Returns an iterator of paired items, overlapping, from the original > > >>> take(4, pairwise(count())) > [(0, 1), (1, 2), (2, 3), (3, 4)] I betcha the implementation of pairwise is something really close to: def pairwise(iterable): it = iter(iterable) return itertools.izip(it, it) for Python 2, and for Python 3: def pairwise(iterable): it = iter(iterable) return zip(it, it) which is all well and good, but what if you want triplets, not pairs? def threewise(iterable): it = iter(iterable) return zip(it, it, it) I don't think it's very practical to include a *wise for every possible number of items... Let's deal some cards! import random cards = [] for value in "A 2 3 4 5 6 7 8 9 10 J Q K".split(): for suit in u"????": cards.append(value + suit) random.shuffle(cards) deck = iter(cards) hands = zip(*[deck]*8) for name in "Groucho Chico Harpo Zeppo Gummo".split(): print("%s gets dealt %s" % (name, ','.join(next(hands)))) I get these results, but being random of course you will get something different: Groucho gets dealt 8?,2?,5?,7?,8?,7?,6?,8? Chico gets dealt Q?,K?,3?,7?,K?,J?,9?,10? Harpo gets dealt 10?,4?,4?,A?,A?,K?,3?,J? Zeppo gets dealt 5?,A?,3?,Q?,9?,9?,4?,2? Gummo gets dealt J?,Q?,4?,10?,J?,6?,5?,A? -- Steve From breamoreboy at yahoo.co.uk Wed Apr 1 16:19:11 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 01 Apr 2015 15:19:11 +0100 Subject: [Tutor] Python Idioms? In-Reply-To: <20150401131630.GU25453@ando.pearwood.info> References: <20150401131630.GU25453@ando.pearwood.info> Message-ID: On 01/04/2015 14:16, Steven D'Aprano wrote: > On Wed, Apr 01, 2015 at 12:06:33PM +0100, Mark Lawrence wrote: > >> In which case I'll stick with the more-itertools pairwise() function >> which I pointed out on another thread just yesterday. From >> http://pythonhosted.org//more-itertools/api.html >> >> >> Returns an iterator of paired items, overlapping, from the original >> >>>>> take(4, pairwise(count())) >> [(0, 1), (1, 2), (2, 3), (3, 4)] > > I betcha the implementation of pairwise is something really close to: > > def pairwise(iterable): > it = iter(iterable) > return itertools.izip(it, it) > > for Python 2, and for Python 3: > > def pairwise(iterable): > it = iter(iterable) > return zip(it, it) > Not a bad attempt :) It's actually. def pairwise(iterable): """Returns an iterator of paired items, overlapping, from the original >>> take(4, pairwise(count())) [(0, 1), (1, 2), (2, 3), (3, 4)] """ a, b = tee(iterable) next(b, None) return zip(a, b) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From colin.ross.dal at gmail.com Wed Apr 1 16:43:56 2015 From: colin.ross.dal at gmail.com (Colin Ross) Date: Wed, 1 Apr 2015 11:43:56 -0300 Subject: [Tutor] Python serial interface Message-ID: Hi all, This is a very general question, but I was wondering if anyone has experience using python to interface with a serial port? If so, can you please forward any useful resources? Thanks! Colin From francois.dion at gmail.com Wed Apr 1 16:53:17 2015 From: francois.dion at gmail.com (Francois Dion) Date: Wed, 1 Apr 2015 10:53:17 -0400 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: Pyserial is python 2.x and 3.x compatible. It is very widely used and is stable. http://pyserial.sourceforge.net/ What is your application? Sometimes you can use a higher level module that makes use of pyserial. Francois -- raspberry-python.blogspot.com - www.pyptug.org - www.3DFutureTech.info - @f_dion From breamoreboy at yahoo.co.uk Wed Apr 1 16:56:35 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 01 Apr 2015 15:56:35 +0100 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: On 01/04/2015 15:43, Colin Ross wrote: > Hi all, > > This is a very general question, but I was wondering if anyone has > experience using python to interface with a serial port? If so, can you > please forward any useful resources? > > Thanks! > > Colin > http://pyserial.sourceforge.net/ -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From colin.ross.dal at gmail.com Wed Apr 1 17:01:31 2015 From: colin.ross.dal at gmail.com (Colin Ross) Date: Wed, 1 Apr 2015 12:01:31 -0300 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: Hi Francois, Thank you for the fast reply! I am looking to control a brushless servo motor ( http://www.aerotech.com/product-catalog/motors/rotary-motors/bms-series.aspx) that drives a rotary stage. Colin On Wed, Apr 1, 2015 at 11:53 AM, Francois Dion wrote: > Pyserial is python 2.x and 3.x compatible. It is very widely used and is > stable. > > http://pyserial.sourceforge.net/ > > What is your application? Sometimes you can use a higher level module that > makes use of pyserial. > > Francois > -- > raspberry-python.blogspot.com - www.pyptug.org - www.3DFutureTech.info - > @f_dion > From francois.dion at gmail.com Wed Apr 1 17:50:13 2015 From: francois.dion at gmail.com (Francois Dion) Date: Wed, 1 Apr 2015 11:50:13 -0400 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: On Wed, Apr 1, 2015 at 11:01 AM, Colin Ross wrote: > Hi Francois, > > Thank you for the fast reply! I am looking to control a brushless servo > motor ( > http://www.aerotech.com/product-catalog/motors/rotary-motors/bms-series.aspx) > that drives a rotary stage. > These motors are not controlled by serial, you'll need a brushless controller. In turn the controller might be or not serial, or ip or something else altogether (PWM is typical). They do have an rs-422 connection, but that is for a feedback signal. So you are building a feedback control system. If you google that and python you'll find several useful references, including a design and analysis module (but not control): https://pypi.python.org/pypi/control/0.6.6 http://sourceforge.net/projects/python-control/ Nothing out of the box for your application, obviously. Also, the motor control itself will depend on the microprocessor hardware you are using and the motor controller. Assuming PWM, the raspberry pi has a software PWM module in Python. Same with micropython. Anything else is pretty much DIY. As for the overall concept of control systems, Chapter 9 of "Real World Instrumentation" ( http://shop.oreilly.com/product/9780596809577.do ) will give you an overview of what is involved (with some python example, but not directly applicable to your system). Francois -- raspberry-python.blogspot.com - www.pyptug.org - www.3DFutureTech.info - @f_dion From colin.ross.dal at gmail.com Wed Apr 1 17:58:17 2015 From: colin.ross.dal at gmail.com (Colin Ross) Date: Wed, 1 Apr 2015 12:58:17 -0300 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: Thank you Francois, this gives me a lot to think about! I really appreciate your feedback. Colin On Wed, Apr 1, 2015 at 12:50 PM, Francois Dion wrote: > On Wed, Apr 1, 2015 at 11:01 AM, Colin Ross > wrote: > >> Hi Francois, >> >> Thank you for the fast reply! I am looking to control a brushless servo >> motor ( >> http://www.aerotech.com/product-catalog/motors/rotary-motors/bms-series.aspx) >> that drives a rotary stage. >> > > These motors are not controlled by serial, you'll need a brushless > controller. In turn the controller might be or not serial, or ip or > something else altogether (PWM is typical). They do have an rs-422 > connection, but that is for a feedback signal. So you are building a > feedback control system. If you google that and python you'll find several > useful references, including a design and analysis module (but not control): > > https://pypi.python.org/pypi/control/0.6.6 > http://sourceforge.net/projects/python-control/ > > Nothing out of the box for your application, obviously. Also, the motor > control itself will depend on the microprocessor hardware you are using and > the motor controller. Assuming PWM, the raspberry pi has a software PWM > module in Python. Same with micropython. Anything else is pretty much DIY. > > As for the overall concept of control systems, Chapter 9 of "Real World > Instrumentation" ( http://shop.oreilly.com/product/9780596809577.do ) > will give you an overview of what is involved (with some python example, > but not directly applicable to your system). > > Francois > -- > raspberry-python.blogspot.com - www.pyptug.org - www.3DFutureTech.info > - @f_dion > From colin.ross.dal at gmail.com Wed Apr 1 18:14:54 2015 From: colin.ross.dal at gmail.com (Colin Ross) Date: Wed, 1 Apr 2015 13:14:54 -0300 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: I am using the following controller: http://www.aerotech.com/product-catalog/drives-and-drive-racks/ensemble-mp.aspx Which does not specifically list python as one of the accepted languages, but I guess this does not mean it is not possible. Colin On Wed, Apr 1, 2015 at 12:58 PM, Colin Ross wrote: > Thank you Francois, this gives me a lot to think about! > > I really appreciate your feedback. > > Colin > > On Wed, Apr 1, 2015 at 12:50 PM, Francois Dion > wrote: > >> On Wed, Apr 1, 2015 at 11:01 AM, Colin Ross >> wrote: >> >>> Hi Francois, >>> >>> Thank you for the fast reply! I am looking to control a brushless servo >>> motor ( >>> http://www.aerotech.com/product-catalog/motors/rotary-motors/bms-series.aspx) >>> that drives a rotary stage. >>> >> >> These motors are not controlled by serial, you'll need a brushless >> controller. In turn the controller might be or not serial, or ip or >> something else altogether (PWM is typical). They do have an rs-422 >> connection, but that is for a feedback signal. So you are building a >> feedback control system. If you google that and python you'll find several >> useful references, including a design and analysis module (but not control): >> >> https://pypi.python.org/pypi/control/0.6.6 >> http://sourceforge.net/projects/python-control/ >> >> Nothing out of the box for your application, obviously. Also, the motor >> control itself will depend on the microprocessor hardware you are using and >> the motor controller. Assuming PWM, the raspberry pi has a software PWM >> module in Python. Same with micropython. Anything else is pretty much DIY. >> >> As for the overall concept of control systems, Chapter 9 of "Real World >> Instrumentation" ( http://shop.oreilly.com/product/9780596809577.do ) >> will give you an overview of what is involved (with some python example, >> but not directly applicable to your system). >> >> Francois >> -- >> raspberry-python.blogspot.com - www.pyptug.org - www.3DFutureTech.info >> - @f_dion >> > > From roel at roelschroeven.net Wed Apr 1 19:20:12 2015 From: roel at roelschroeven.net (Roel Schroeven) Date: Wed, 01 Apr 2015 19:20:12 +0200 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: Mark Lawrence schreef: > On 01/04/2015 11:50, Alan Gauld wrote: >> On 01/04/15 11:04, Wolfgang Maier wrote: >>> On 04/01/2015 11:04 AM, Alan Gauld wrote: >>>> On 01/04/15 05:50, Jim Mooney wrote: >>>> >>>>>>>> s = [1,2,3,4,5,6,7,8] >>>>>>>> list(zip(*[iter(s)]*2)) >>>>>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] >>>> Personally I'd have used slicing in this example: >>>> >>>> zip(s[::2],s[1::2]) >>>> >>> With an emphasis on *in this example*. >>> >>> The idiom you are citing works on any iterable, not all of which support >>> slicing and the slicing version requires two passes over the data. >> Agreed, but readability always trumps performance, >> unless performance is critical. >> In which case readability usually trumps performance. >> >> And especially on a beginners list. >> > > In which case I'll stick with the more-itertools pairwise() function Which does not the same thing. Original: >>>>>>>> s = [1,2,3,4,5,6,7,8] >>>>>>>> list(zip(*[iter(s)]*2)) >>>>>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] Pairwise: > >>> take(4, pairwise(count())) > [(0, 1), (1, 2), (2, 3), (3, 4)] Greetings, Roel -- The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom. -- Isaac Asimov Roel Schroeven From breamoreboy at yahoo.co.uk Wed Apr 1 22:25:27 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 01 Apr 2015 21:25:27 +0100 Subject: [Tutor] Python serial interface In-Reply-To: References: Message-ID: On 01/04/2015 17:14, Colin Ross wrote: > I am using the following controller: > > http://www.aerotech.com/product-catalog/drives-and-drive-racks/ensemble-mp.aspx > > Which does not specifically list python as one of the accepted languages, > but I guess this does not mean it is not possible. > > Colin Can you please stop top posting, it's extremely irritating trying to follow fairly long threads like this, thanks. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From breamoreboy at yahoo.co.uk Wed Apr 1 22:59:30 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 01 Apr 2015 21:59:30 +0100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: On 01/04/2015 18:20, Roel Schroeven wrote: > Mark Lawrence schreef: >> On 01/04/2015 11:50, Alan Gauld wrote: >>> On 01/04/15 11:04, Wolfgang Maier wrote: >>>> On 04/01/2015 11:04 AM, Alan Gauld wrote: >>>>> On 01/04/15 05:50, Jim Mooney wrote: >>>>> >>>>>>>>> s = [1,2,3,4,5,6,7,8] >>>>>>>>> list(zip(*[iter(s)]*2)) >>>>>>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] >>>>> Personally I'd have used slicing in this example: >>>>> >>>>> zip(s[::2],s[1::2]) >>>>> >>>> With an emphasis on *in this example*. >>>> >>>> The idiom you are citing works on any iterable, not all of which >>>> support >>>> slicing and the slicing version requires two passes over the data. >>> Agreed, but readability always trumps performance, >>> unless performance is critical. >>> In which case readability usually trumps performance. >>> >>> And especially on a beginners list. >>> >> >> In which case I'll stick with the more-itertools pairwise() function > > Which does not the same thing. Original: > > >>>>>>>> s = [1,2,3,4,5,6,7,8] > >>>>>>>> list(zip(*[iter(s)]*2)) > >>>>>>>> [(1, 2), (3, 4), (5, 6), (7, 8)] > > Pairwise: > >> >>> take(4, pairwise(count())) >> [(0, 1), (1, 2), (2, 3), (3, 4)] > > > Greetings, > Roel > Yo are of course completely correct, I was conflating two different threads :) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From steve at pearwood.info Thu Apr 2 00:08:59 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 2 Apr 2015 09:08:59 +1100 Subject: [Tutor] Python Idioms? In-Reply-To: References: Message-ID: <20150401220858.GV25453@ando.pearwood.info> On Wed, Apr 01, 2015 at 09:59:30PM +0100, Mark Lawrence wrote: [snip mass quoting] > Yo are of course completely correct, I was conflating two different > threads :) Hey guys, how about trimming some of the excessive quoting in your posts? Especially if you're going to complain about the annoyance of top-posting, bottom-posting without trimming is actually *worse* and more distruptive to ease of reading. After I've flipped through two pages of quotes without any new comments at all, I'm sorely tempted to just hit Delete on the rest unread. -- Steve From abdalimran at live.com Wed Apr 1 21:22:05 2015 From: abdalimran at live.com (Abdullah Al Imran) Date: Thu, 2 Apr 2015 01:22:05 +0600 Subject: [Tutor] How do I make pattern to find only '.html' file using Python Regular Expression? Message-ID: I have some HTML content where there are many links as the following pattern: Problem No-1
I want to filter all the links into a list as: ['http://example.com/2013/01/problem1.html', 'http://example.com/2013/02/problem2.html'] How to do it using Python Regular Expression? If I want to filter all the links into a dictionary as: ['http://example.com/2013/01/problem1.html':'Problem No-1', 'http://example.com/2013/02/problem2.html ':'Problem No-2',] How do I do it? From alan.gauld at btinternet.com Thu Apr 2 01:02:17 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 00:02:17 +0100 Subject: [Tutor] How do I make pattern to find only '.html' file using Python Regular Expression? In-Reply-To: References: Message-ID: On 01/04/15 20:22, Abdullah Al Imran wrote: > I have some HTML content where there are many links as the following pattern: > > Problem No-1
> > I want to filter all the links into a list as: > ['http://example.com/2013/01/problem1.html', 'http://example.com/2013/02/problem2.html'] > > How to do it using Python Regular Expression? You can try, but regular expressions are not a reliable way to parse HTML. You are much better to use a dedicated HTML parser such as the one found in htmllib in the standard library or a third party tool like BeautifulSoup. These recognise the different tag types and separate the content and data for you. You can then just ask for the parser to find tags and then fetch the data from each tag. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From ben+python at benfinney.id.au Thu Apr 2 01:47:21 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Thu, 02 Apr 2015 10:47:21 +1100 Subject: [Tutor] How do I make pattern to find only '.html' file using Python Regular Expression? References: Message-ID: <85k2xv1kdy.fsf@benfinney.id.au> Abdullah Al Imran writes: > How to do it using Python Regular Expression? Don't assume which tool you must use; instead, ask how best the problem can be solved. In the case of parsing HTML, regular expressions are a poor fit because they're not doing the job of parsing. Use a parser which better understands HTML, like Beautiful Soup . -- \ ?An expert is a man who has made all the mistakes which can be | `\ made in a very narrow field.? ?Niels Bohr | _o__) | Ben Finney From ahlusar.ahluwalia at gmail.com Thu Apr 2 02:08:39 2015 From: ahlusar.ahluwalia at gmail.com (Saran Ahluwalia) Date: Wed, 1 Apr 2015 20:08:39 -0400 Subject: [Tutor] Question for Strategy for Directory Monitor Message-ID: Good Evening : Here is what I want me program to do: ? *Monitor* a folder for files that are dropped throughout the day ? When a file is dropped in the folder the program should scan the file o IF all the contents in the file have the same length (let's assume line length) o THEN the file should be moved to a "success" folder and a text file written indicating the total number of records/lines/words processed o IF the file is empty OR the contents are not all of the same length o THEN the file should be moved to a "failure" folder and a text file written indicating the cause for failure (for example: Empty file or line 100 was not the same length as the rest). I want to thank Martin Brown for his guidance and feedback. I welcome any and all feedback on the following import os import time import glob import sys def initialize_logger(output_dir): logger = logging.getLogger() logger.setLevel(logging.DEBUG) # create console handler and set level to info handler = logging.StreamHandler() handler.setLevel(logging.INFO) formatter = logging.Formatter("%(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) # create error file handler and set level to error handler = logging.FileHandler(os.path.join(output_dir, "error.log"),"w", encoding=None, delay="true") handler.setLevel(logging.ERROR) formatter = logging.Formatter("%(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) # create debug file handler and set level to debug handler = logging.FileHandler(os.path.join(output_dir, "all.log"),"w") handler.setLevel(logging.DEBUG) formatter = logging.Formatter("%(levelname)s - %(message)s") handler.setFormatter(formatter) logger.addHandler(handler) def main(dirslist): while True: for file in os.listdir(dirslist) : return validate_files(file) time.sleep(5) if __name__ == "__main__": main() *#Helper Functions for the Success and Failure Folder Outcomes, respectively* def file_len(filename): with open(filename) as f: for i, l in enumerate(f): pass return i + 1 def copyFile(src, dest): try: shutil.copy(src, dest) # eg. src and dest are the same file except shutil.Error as e: print('Error: %s' % e) # eg. source or destination doesn't exist except IOError as e: print('Error: %s' % e.strerror) def move_to_failure_folder_and_return_error_file(): os.mkdir('Failure') copyFile(filename, 'Failure') initialize_logger('rootdir/Failure') logging.error("Either this file is empty or the lines") def move_to_success_folder_and_read(file): os.mkdir('Success') copyFile(filename, 'Success') print("Success", file) return file_len() #This simply checks the file information by name def fileinfo(file): filename = os.path.basename(file) rootdir = os.path.dirname(file) lastmod = time.ctime(os.path.getmtime(file)) creation = time.ctime(os.path.getctime(file)) filesize = os.path.getsize(file) return filename, rootdir, lastmod, creation, filesize if __name__ == '__main__': import sys validate_files(sys.argv[1:]) I am trying to specifically address the fact that the program does not: - Assumes that all filenames come directly from the commandline. No searching of a directory. - The present code does not move any files to success or failure directories (I have added functions at the end that could serve as substitutes) - The present code doesn't calculate or write to a text file. - The present code runs once through the names, and terminates. It doesn't "monitor" anything - I think that I have added the correct while loop. - The present code doesn't check for zero-length files I have attempted to address these but, as a novice, am not sure what is best practice. Sincerely, Saran From jnl_public at yahoo.com Thu Apr 2 08:36:03 2015 From: jnl_public at yahoo.com (J L) Date: Thu, 2 Apr 2015 06:36:03 +0000 (UTC) Subject: [Tutor] Command Line Editting: How to improve options? Message-ID: <767754435.3505039.1427956563329.JavaMail.yahoo@mail.yahoo.com> ?Win 7Python v 3.4.3 I'm new to Python and only have coursework under my belt in another object oriented programming language as well as limited systems skills. After launching Python?from the command line with py.exe, it appears that the interrupter starts up fine. I've read on Python.Org's site in a tutorial section that some interrupters offer command line editing beyond simple use of the arrow keys and backspace. It does not appear that my environment is allowing these greater abilities. How does one afford increased abilities to edit commands within Python's interrupter? Thank you. From joe.farro at gmail.com Thu Apr 2 05:18:21 2015 From: joe.farro at gmail.com (Joe Farro) Date: Wed, 1 Apr 2015 23:18:21 -0400 Subject: [Tutor] Request review: A DSL for scraping a web page Message-ID: Hello, I recently wrote a python package and was wondering if anyone might have time to review it? I'm fairly new to python - it's been about 1/2 of my workload at work for the past year. Any suggestions would be super appreciated. https://github.com/tiffon/take https://pypi.python.org/pypi/take The package implements a DSL that is intended to make web-scraping a bit more maintainable :) I generally find my scraping code ends up being rather chaotic with querying, regex manipulations, conditional processing, conversions, etc., ending up being to close together and sometimes interwoven. It's stressful. The DSL attempts to mitigate this by doing only two things: finding stuff and saving it as a string. The post-processing is left to be done down the pipeline. It's almost just a configuration file. Here is an example that would get the text and URL for every link in a page: $ a save each: links | [href] save: url | text save: link_text The result would be something along these lines: { 'links': [ { 'url': 'http://www.something.com/hm', 'link_text': 'The text in the link' }, # etc... another dict for each tag ] } The hope is that having all the selectors in one place will make them more manageable and possibly simplify the post-processing. This is my first go at something along these lines, so any feedback is welcomed. Thanks! Joe From alan.gauld at btinternet.com Thu Apr 2 10:10:02 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 09:10:02 +0100 Subject: [Tutor] Command Line Editting: How to improve options? In-Reply-To: <767754435.3505039.1427956563329.JavaMail.yahoo@mail.yahoo.com> References: <767754435.3505039.1427956563329.JavaMail.yahoo@mail.yahoo.com> Message-ID: On 02/04/15 07:36, J L wrote: > Win 7Python v 3.4.3 > After launching Python from the command line with py.exe, it appears that the interrupter starts up fine. Thats interpreter, not interrupter. It interprets your commands. > I've read on Python.Org's site in a tutorial section that some interrupters > offer command line editing The easiest way for you to get that is to use IDLE, the development tool for Python. There should be a menu entry on your OS to launch IDLE (sometimes called 'Python GUI'). The IDLE interactive shell allows you to use cut n paste, as well as keys such as Alt-UP/DOWN to cycle through history etc. You can get most of these features in the Windows CMD.exe too but you need to set some registry entries. Typing HELP CMD at the OS prompt brings up a long page describing the features you can choose to turn on and how. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Thu Apr 2 10:22:02 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 09:22:02 +0100 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: References: Message-ID: On 02/04/15 04:18, Joe Farro wrote: > Hello, > > I recently wrote a python package and was wondering if anyone might have > time to review it? This list is for people learning Python and answering questions about the core language and standard library. I suspect this is more appropriate to the main python list. However to make any meaningful comments we would probably need a bit more of a specification to know what your module does. > The package implements a DSL that is intended to make web-scraping a bit > more maintainable :) DSL? > I generally find my scraping code ends up being rather chaotic with > querying, regex manipulations, conditional processing, conversions, etc., > ending up being to close together and sometimes interwoven. It's stressful. Have you looked at the existing web scraping tools in Python? There are several to pick from. They all avoid the kind of mess you describe. > The DSL attempts to mitigate this by doing only two things: > finding stuff and saving it as a string. The post-processing > is left to be done down the pipeline. It's almost just > a configuration file. > Here is an example that would get the text and URL for every link in a page: > > $ a > save each: links > | [href] > save: url > | text > save: link_text And how is that run? What is the syntax for the config file? It is not self evident. The other example on github is no less obscure. I'm sure it means something to you but it is not obvious. OK, I see there is much more on the github. Sadly too much for me to plough through just now. > The result would be something along these lines: > > { > 'links': [ > { > 'url': 'http://www.something.com/hm', > 'link_text': 'The text in the link' > }, > # etc... another dict for each tag > ] > } This seems straightforward. > The hope is that having all the selectors in one place will make them more > manageable and possibly simplify the post-processing. > > This is my first go at something along these lines, so any feedback is > welcomed. I think the main python list is a better bet for feedback on something of this size. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Thu Apr 2 11:50:38 2015 From: davea at davea.name (Dave Angel) Date: Thu, 02 Apr 2015 05:50:38 -0400 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: References: Message-ID: <551D10EE.1060008@davea.name> On 04/02/2015 04:22 AM, Alan Gauld wrote: > > DSL? > This is "Domain Specific Language". This is a language built around a specific problem domain, in order to more easily express problems for that domain than the usual general purpose languages. I was a bit surprised to find few google matches, but here's one: http://www.pcmag.com/encyclopedia/term/41694/domain-specific-language and of course http://en.wikipedia.org/wiki/DSL_(disambiguation) -- DaveA From alan.gauld at btinternet.com Thu Apr 2 12:41:02 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 11:41:02 +0100 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: <551D10EE.1060008@davea.name> References: <551D10EE.1060008@davea.name> Message-ID: On 02/04/15 10:50, Dave Angel wrote: > On 04/02/2015 04:22 AM, Alan Gauld wrote: >> >> DSL? > > This is "Domain Specific Language". This is a language built around a > specific problem domain, Ah, Thanks Dave! I am used to those being called simply "Little languages" after the famous Jon Bently ACM article that introduced the concept. http://c2.com/cgi/wiki?LittleLanguage DSL especially confused me because we had an in-house language called that, but it wasn't available outside so I didn't see how the OP could be using it :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Thu Apr 2 13:09:49 2015 From: davea at davea.name (Dave Angel) Date: Thu, 02 Apr 2015 07:09:49 -0400 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: References: <551D10EE.1060008@davea.name> Message-ID: <551D237D.8070100@davea.name> On 04/02/2015 06:41 AM, Alan Gauld wrote: > On 02/04/15 10:50, Dave Angel wrote: >> On 04/02/2015 04:22 AM, Alan Gauld wrote: >>> >>> DSL? >> >> This is "Domain Specific Language". This is a language built around a >> specific problem domain, > > Ah, Thanks Dave! > I am used to those being called simply "Little languages" after the > famous Jon Bently ACM article that introduced the concept. > > http://c2.com/cgi/wiki?LittleLanguage > > DSL especially confused me because we had an in-house language > called that, but it wasn't available outside so I didn't see > how the OP could be using it :-) > Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls books, and have a trip down memory lane. I bet 95% of those are still useful, even if they refer to much earlier versions of language(s). I also should find myself a modern Forth system, and see how that's evolved over time. Years ago I was an observer on the ANSI Forth standard, as well as newsletter editor for the local FIG. -- DaveA From alan.gauld at btinternet.com Thu Apr 2 13:17:44 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 12:17:44 +0100 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: <551D237D.8070100@davea.name> References: <551D10EE.1060008@davea.name> <551D237D.8070100@davea.name> Message-ID: On 02/04/15 12:09, Dave Angel wrote: > Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls > books, and have a trip down memory lane. I bet 95% of those are still > useful, even if they refer to much earlier versions of language(s). Yes, the Pearls books should be required reading for all new programmers. The lessons are pretty timeless, it's only the languages that change - and most of his examples seem to be in a kind of pseudo Pascal dialect rather than real code anyway. I believe they've been re-released as a single volume now. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Thu Apr 2 13:22:19 2015 From: davea at davea.name (Dave Angel) Date: Thu, 02 Apr 2015 07:22:19 -0400 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: References: <551D10EE.1060008@davea.name> <551D237D.8070100@davea.name> Message-ID: <551D266B.9000800@davea.name> On 04/02/2015 07:17 AM, Alan Gauld wrote: > On 02/04/15 12:09, Dave Angel wrote: > >> Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls >> books, and have a trip down memory lane. I bet 95% of those are still >> useful, even if they refer to much earlier versions of language(s). > > Yes, the Pearls books should be required reading for all new > programmers. The lessons are pretty timeless, it's only the > languages that change - and most of his examples seem to be > in a kind of pseudo Pascal dialect rather than real code anyway. > > I believe they've been re-released as a single volume now. > There was somewhere in one of the books a list of 'good practice,' including an item something like: Solve the right problem. There's a world of wisdom in that one alone. -- DaveA From __peter__ at web.de Thu Apr 2 13:43:37 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 02 Apr 2015 13:43:37 +0200 Subject: [Tutor] Request review: A DSL for scraping a web page References: Message-ID: Joe Farro wrote: > The package implements a DSL that is intended to make web-scraping a bit > more maintainable :) > > I generally find my scraping code ends up being rather chaotic with > querying, regex manipulations, conditional processing, conversions, etc., > ending up being to close together and sometimes interwoven. It's > stressful. Everything is cleaner than a bunch of regular expressions. It's just that sometimes they give results more quickly and as reliable as you can get without adding a javascript engine to your script. > The DSL attempts to mitigate this by doing only two things: > finding stuff and saving it as a string. The post-processing is left to be > done down the pipeline. It's almost just a configuration file. > > Here is an example that would get the text and URL for every link in a > page: > > $ a > save each: links > | [href] > save: url > | text > save: link_text > > > The result would be something along these lines: > > { > 'links': [ > { > 'url': 'http://www.something.com/hm', > 'link_text': 'The text in the link' > }, > # etc... another dict for each tag > ] > } > With beautiful soup you could write this soup = bs4.BeautifulSoup(...) links = [ { "url": a["href"], "link_text": a.text } for a in soup("a") ] and for many applications you wouldn't even bother with the intermediate data structure. Can you give a real-world example where your DSL is significantly cleaner than the corresponding code using bs4, or lxml.xpath, or lxml.objectify? > The hope is that having all the selectors in one place will make them more > manageable and possibly simplify the post-processing. > > This is my first go at something along these lines, so any feedback is > welcomed. Your code on github looks good to me (too few docstrings), but like Alan I'm not prepared to read it completely. Do you have specific questions? From steve at pearwood.info Thu Apr 2 14:07:51 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 2 Apr 2015 23:07:51 +1100 Subject: [Tutor] Command Line Editting: How to improve options? In-Reply-To: <767754435.3505039.1427956563329.JavaMail.yahoo@mail.yahoo.com> References: <767754435.3505039.1427956563329.JavaMail.yahoo@mail.yahoo.com> Message-ID: <20150402120751.GX25453@ando.pearwood.info> On Thu, Apr 02, 2015 at 06:36:03AM +0000, J L wrote: > ?Win 7Python v 3.4.3 > I'm new to Python and only have coursework under my belt in another > object oriented programming language as well as limited systems > skills. After launching Python?from the command line with py.exe, it > appears that the interrupter starts up fine. I've read on Python.Org's > site in a tutorial section that some interrupters offer command line > editing beyond simple use of the arrow keys and backspace. It does not > appear that my environment is allowing these greater abilities. How > does one afford increased abilities to edit commands within Python's > interrupter? Thank you. Sadly, Windows does not offer much in the way of powerful interactive commands like most Linux shells do. You can try these options: - try using Python's IDLE: http://www.google.com.au/search?q=how+to+run+IDLE+python - Use a commercial third-party IDE ("Integrated Development Environment") such as PyCharm, Anaconda or Komodo. Some of them may cost money, but they may have free or trial versions. - Or a third-party editor such as Spyder, if it comes with its own interactive shell. - I can strongly recomment iPython, which is very powerful and includes a lot of command-line features that even Linux shells don't: http://ipython.org/ ? If you've used Mathematica, you may love iPython's "notepad" feature. Now we start getting to slightly more complex options, which may not work, but it would be interesting to try: - Try installing pyreadline, and see it is will work with Python 3.4. If it does, you might be able to convince Python 3.4's rlcompleter module to work with it. - Still if pyreadline works with Python 3.4, you might like my command line tab completer and history module rather than the built-in one: http://code.google.com/p/tabhistory/source/browse/tabhistory.py I've never tested it on Windows, so I don't know if it will actually work or not. Good luck! -- Steve From wolfrage8765 at gmail.com Thu Apr 2 18:18:28 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Thu, 02 Apr 2015 12:18:28 -0400 Subject: [Tutor] Functional Programming in Python Message-ID: <551D6BD4.8030507@gmail.com> These are just some questions that I have regarding the topic of Functional Programming. I am working towards a more functional approach to programming but acknowledge that it is far from Functional, especially since this is mostly impossible in Python. Questions: What are the best practices to create more Functional Python? What are your thoughts on Functional in Python? Currently I am re-writing functions to reduce their side effects. I am also removing the state from objects and putting it into a closure type function. However with callback based systems (GUI) this seemed impossible, so instead I am abusing a coroutine to maintain the state of the application. But is it abuse or does it seem like a good way to handle the callback system? The benefit to me at this time is limited, but any errors in state are confined to a single location, which is nice. What do you think about using a coroutine to handle state, how would you do it better in a callback based system. Thank you for your insights. From ahlusar.ahluwalia at gmail.com Thu Apr 2 14:28:50 2015 From: ahlusar.ahluwalia at gmail.com (Saran Ahluwalia) Date: Thu, 2 Apr 2015 08:28:50 -0400 Subject: [Tutor] New to Programming: TypeError: coercing to Unicode: need string or buffer, list found Message-ID: Good Morning: I understand this error message when I run this code. However, I am curious to know what the most pythonic way is to convert the list to a string? I use Python 2.7. "Traceback (most recent call last): before = dict([(f, None) for f in os.listdir(dirlist)]) TypeError: coercing to Unicode: need string or buffer, list found" The sample code that I am trying to run is: path = "/Users/Desktop/Projects/" dirlist = os.listdir(path) before = dict([(f, None) for f in os.listdir(dirlist)]) def main(dirlist): while True: time.sleep(10) #time between update check after = dict([(f, None) for f in os.listdir(dirlist)]) added = [f for f in after if not f in before] if added: print('Successfully added new file - ready to validate') if __name__ == "__main__": main() From joe.farro at gmail.com Thu Apr 2 16:54:01 2015 From: joe.farro at gmail.com (Joe Farro) Date: Thu, 2 Apr 2015 14:54:01 +0000 (UTC) Subject: [Tutor] Request review: A DSL for scraping a web page References: Message-ID: Alan Gauld btinternet.com> writes: > DSL? Good to know the term/acronym is not ubiquitous. I was going for succinct, possibly too succinct... > Have you looked at the existing web scraping tools in Python? > There are several to pick from. They all avoid the kind of mess > you describe. I'm familiar with a few of them. I've used beautiful soup, PyQuery, and cssselect. I got frustrated with my scraping code and wrote the DSL. It's still in the "proving ground" phase of things. A later post asked about a real-world sample, I'm going to work something up. > And how is that run? > What is the syntax for the config file? > It is not self evident. The other example on github is no less obscure. > I'm sure it means something to you but it is not obvious. > > OK, I see there is much more on the github. Sadly too much for me to > plough through just now. Thanks for looking. > I think the main python list is a better bet for feedback on something > of this size. I wasn't sure if this was sort of at that level, thanks for the suggestion. From joe.farro at gmail.com Thu Apr 2 17:08:22 2015 From: joe.farro at gmail.com (Joe Farro) Date: Thu, 2 Apr 2015 15:08:22 +0000 (UTC) Subject: [Tutor] Request review: A DSL for scraping a web page References: Message-ID: Thanks, Peter. Peter Otten <__peter__ web.de> writes: > Can you give a real-world example where your DSL is significantly cleaner > than the corresponding code using bs4, or lxml.xpath, or lxml.objectify? Yes, definitely. Will work something up. > Your code on github looks good to me (too few docstrings), but like Alan I'm > not prepared to read it completely. Do you have specific questions? Well, the questions raised (how is it an upgrade) are great food for thought. The idea and effort were born from legitimate frustrations, but it's not exactly battle-tested, yet. I'll work up a few examples (the first to come, shortly). But, great to know nothing immediately disastrous jumps out in the code. I do have specific questions, but first I want to work up the use-case, if that looks weak, the other concerns might be a non-issue. From alan.gauld at btinternet.com Thu Apr 2 19:07:18 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 18:07:18 +0100 Subject: [Tutor] Functional Programming in Python In-Reply-To: <551D6BD4.8030507@gmail.com> References: <551D6BD4.8030507@gmail.com> Message-ID: On 02/04/15 17:18, WolfRage wrote: > to programming but acknowledge that it is far from Functional, > especially since this is mostly impossible in Python. I'm not sure what you mean is impossible? The specific issues you are having or the general FP paradigm? Python has fairly good support for FP, much better than most non-FP-specific languages. > Questions: > What are the best practices to create more Functional Python? Everything goes in functions which do not change their inputs and return outputs. Use tools like itertools and functools to avoid explicit loops. > What are your thoughts on Functional in Python? It's good enough to use where the problem suits FP. It's no more a pure FP language than it is a pure OOP language. But in both cases you can get close enough for practical purposes. What is your problem scenario that makes FP seem like the best idiom? > Currently I am re-writing functions to reduce their side effects. Good, nearly always the best way. > I am also removing the state from objects and putting it into a closure > type function. That may or may not be a good idea. FP object handling can get awfully messy and awfully inefficient. > However with callback based systems (GUI) this seemed impossible, so > instead I am abusing a coroutine to maintain the state of the application. Trying to force a non-FP framework(eg a GUI)_ to work in an FP way is usually an exercise in frustration. > But is it abuse or does it seem like a good way to handle the callback > system? The benefit to me at this time is limited, but any errors in > state are confined to a single location, which is nice. That should be true in an OOP based system too. The whole point of OOP is to contain and hide state (as opposed to eliminating it) > What do you think about using a coroutine to handle state, how would you > do it better in a callback based system. Without seeing how you are doing it we can't comment on *better*. We need a baseline. Your approach may be brilliant, or it may be awful, we can't tell. But remember that there is no such thing as the perfect paradigm. FP has many strengths but it has many weaknesses too. As does OOP. Even procedural programming has advantages over OOP and FP in some circumstances. By all means learn the paradigms, but don't get hung up on any one. They all play a part. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From emile at fenx.com Thu Apr 2 19:07:16 2015 From: emile at fenx.com (Emile van Sebille) Date: Thu, 02 Apr 2015 10:07:16 -0700 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: <551D266B.9000800@davea.name> References: <551D10EE.1060008@davea.name> <551D237D.8070100@davea.name> <551D266B.9000800@davea.name> Message-ID: On 4/2/2015 4:22 AM, Dave Angel wrote: > There was somewhere in one of the books a list of 'good practice,' > including an item something like: > > Solve the right problem. > > There's a world of wisdom in that one alone. +1 Emile From danny.yoo at gmail.com Thu Apr 2 19:45:14 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Thu, 2 Apr 2015 10:45:14 -0700 Subject: [Tutor] New to Programming: TypeError: coercing to Unicode: need string or buffer, list found In-Reply-To: References: Message-ID: On Apr 2, 2015 9:45 AM, "Saran Ahluwalia" wrote: > > Good Morning: > > I understand this error message when I run this code. However, I am curious > to know what the most pythonic way is to convert the list to a string? I > use Python 2.7. > > "Traceback (most recent call last): > before = dict([(f, None) for f in os.listdir(dirlist)]) > TypeError: coercing to Unicode: need string or buffer, list found" I actually do not understand the error. :p In particular, I do not understand the subexpression: os.listdir(dirlist) Can you explain what you are trying to do there? The listdir function only consumes single strings, so this looks like a mistake unless dirlist is a string. From steve at pearwood.info Thu Apr 2 20:07:13 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 3 Apr 2015 05:07:13 +1100 Subject: [Tutor] Functional Programming in Python In-Reply-To: <551D6BD4.8030507@gmail.com> References: <551D6BD4.8030507@gmail.com> Message-ID: <20150402180712.GY25453@ando.pearwood.info> On Thu, Apr 02, 2015 at 12:18:28PM -0400, WolfRage wrote: > These are just some questions that I have regarding the topic of > Functional Programming. I am working towards a more functional approach > to programming but acknowledge that it is far from Functional, > especially since this is mostly impossible in Python. It is true that Python is not a purely functional language, like Haskell, but that does not stop you from writing code in a functional style. > Questions: > What are the best practices to create more Functional Python? Best practices: * Don't force your code to use one style exclusively. Use the most natural style for the task. Python makes it easy to mix functional, procedural, imperative and object oriented code in the one application. Use whatever is most natural for your task. * Where possible, write your functions and methods in a functional style. That means: - Avoid global variables. - Avoid side-effects where possible. - Separate the logic of your algorithm from the display of results (e.g. don't have a method that calculates a result AND prints it; have the method calculate the result, and then have the caller print it). - In Python 3, zip(), map() and filter() are lazy iterator functions; in Python 2 they are eager, but there are lazy versions in the itertools module. - In Python 3, reduce() is moved to the functools module. - Many uses of map() and filter() are better written as generator expressions; e.g. instead of: filter(lambda s: s.lower().startswith("a"), map(str, mylist)) you can use: (str(x) for x in mylist if s.lower().startswith("a")) - Where useful, write your code to take advantage of "pipelining" style, e.g. using lazy iterators rather than lists. You can then chain iterators together to get the desired result. > What are your thoughts on Functional in Python? > Currently I am re-writing functions to reduce their side effects. > I am also removing the state from objects and putting it into a closure > type function. That doesn't remove state, it just moves it to a different place. However, encapsulating state inside a closure, or an object, it often the most effective and natural way to deal with a problem. Better than passing around long and confusing numbers of variables! > However with callback based systems (GUI) this seemed impossible, so > instead I am abusing a coroutine to maintain the state of the application. > But is it abuse or does it seem like a good way to handle the callback > system? The benefit to me at this time is limited, but any errors in > state are confined to a single location, which is nice. > What do you think about using a coroutine to handle state, how would you > do it better in a callback based system. What do you mean? Can you show an example? -- Steve From dyoo at hashcollision.org Thu Apr 2 20:52:40 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Thu, 2 Apr 2015 11:52:40 -0700 Subject: [Tutor] Functional Programming in Python In-Reply-To: <20150402180712.GY25453@ando.pearwood.info> References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> Message-ID: >> What are your thoughts on Functional in Python? >> Currently I am re-writing functions to reduce their side effects. >> I am also removing the state from objects and putting it into a closure >> type function. > > That doesn't remove state, it just moves it to a different place. > > However, encapsulating state inside a closure, or an object, it often > the most effective and natural way to deal with a problem. Better than > passing around long and confusing numbers of variables! Theoretically, I'd agree with this. But engineering-wise, I'd recommend explicit structures or objects if possible when representing state. Arbitrary lambdas are unconstrained in what they do. They are raw material for computation. You can do pretty much anything with them. That aspect is often heralded as a positive. But that means that we often need to do more work to make lambdas do things that we'd otherwise do with other built-in features of the language. Let's make this concrete. If we want to represent a coordinate, a pair of numbers, we could use raw closures for this... ################################ def pair(x, y): def dispatch(msg): if msg == 'x': return x if msg == 'y': return y return dispatch p = pair(3, 4) print p('x') print p('y') ################################ And this works! But there's already a feature in the language that does this kind of aggregation. ################################ class pair(object): def __init__(self, x, y): self.x, self.y = x, y p = pair(3, 4) print p.x print p.y ################################# This is something that folks expect and is well supported and understood. This is not to say that closures are bad. It's just to point out that just because functional programs use closures quite a lot, doesn't automatically mean closures are the most appropriate tool for everything. If there are parts of the language that already do the sort of thing you're trying to accomplish, it might be good to reuse those parts, rather than reinvent the universe. From tim at akwebsoft.com Thu Apr 2 21:08:27 2015 From: tim at akwebsoft.com (Tim Johnson) Date: Thu, 2 Apr 2015 11:08:27 -0800 Subject: [Tutor] Functional Programming in Python In-Reply-To: <551D6BD4.8030507@gmail.com> References: <551D6BD4.8030507@gmail.com> Message-ID: <20150402190827.GA5392@mail.akwebsoft.com> * WolfRage [150402 08:25]: > These are just some questions that I have regarding the topic of > Functional Programming. I am working towards a more functional approach > to programming but acknowledge that it is far from Functional, > especially since this is mostly impossible in Python. > Questions: > What are the best practices to create more Functional Python? > What are your thoughts on Functional in Python? > Currently I am re-writing functions to reduce their side effects. > I am also removing the state from objects and putting it into a closure > type function. > However with callback based systems (GUI) this seemed impossible, so > instead I am abusing a coroutine to maintain the state of the application. > But is it abuse or does it seem like a good way to handle the callback > system? The benefit to me at this time is limited, but any errors in > state are confined to a single location, which is nice. > What do you think about using a coroutine to handle state, how would you > do it better in a callback based system. > Thank you for your insights. You have already received valuable replies from two advanced python experts. If you are looking for a book (available digitally for kindle) I would recommend Guide To: Functional Python & Comprehension Constructs by Matt Harrison -- Tim tim at tee jay forty nine dot com or akwebsoft dot com http://www.akwebsoft.com, http://www.tj49.com From wolfrage8765 at gmail.com Thu Apr 2 21:26:53 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Thu, 02 Apr 2015 15:26:53 -0400 Subject: [Tutor] Functional Programming in Python In-Reply-To: References: <551D6BD4.8030507@gmail.com> Message-ID: <551D97FD.2030009@gmail.com> On 04/02/2015 01:07 PM, Alan Gauld wrote: > I'm not sure what you mean is impossible? The specific issues > you are having or the general FP paradigm? I mean achieving truely functional code, atleast to the extent of some of the things that I have read. But in general I do not need nor want any of those special features. I.E. single assignment, optimized tail call, etc. > > Python has fairly good support for FP, much better than > most non-FP-specific languages. I agree. > Everything goes in functions which do not change their inputs and return > outputs. I am getting better at this. > > Use tools like itertools and functools to avoid explicit loops. I am beginning to use them more. > >> What are your thoughts on Functional in Python? > > It's good enough to use where the problem suits FP. It's no > more a pure FP language than it is a pure OOP language. > But in both cases you can get close enough for practical > purposes. What is your problem scenario that makes FP seem > like the best idiom? Since I am making a game, three things got out of control. 1. Managing transitions and instances of objects between transitions. Like loading the Main Menu then starting a Game, then returning to the Menu and Starting a New Game, the old game was still hanging around in memory which becomes a problem on Phones. 2. Side effects have gotten out of hand, and so adding a feature often meant adding bugs. 3. Duplication of code got out of hand. Several functions doing similar things but slightly different. I turned this into pipe-lining to reduce out the different cases and eliminate the duplication. But since it is a game the amount of state does make FP seem very difficult and thus the game is a mixture of OOP and FP, which I am glad to see people saying mix as needed. > >> Currently I am re-writing functions to reduce their side effects. > > Good, nearly always the best way. > >> I am also removing the state from objects and putting it into a closure >> type function. > > That may or may not be a good idea. FP object handling can > get awfully messy and awfully inefficient. > >> However with callback based systems (GUI) this seemed impossible, so >> instead I am abusing a coroutine to maintain the state of the >> application. > > Trying to force a non-FP framework(eg a GUI)_ to work in an FP > way is usually an exercise in frustration. Yeah, it took me awhile to think about what to do in this case. Thus I decided it was best to accept that the interface between the GUI and my code had to be more OOP. > >> But is it abuse or does it seem like a good way to handle the callback >> system? The benefit to me at this time is limited, but any errors in >> state are confined to a single location, which is nice. > > That should be true in an OOP based system too. The whole point > of OOP is to contain and hide state (as opposed to eliminating it) I think since I am mostly self taught I perhaps failed to learn this containment of state until recently. So before now it was fairly common for my state to be spread out amongst several objects. It seems hard for me to contain state in a OOP manor, just because it is so easy to use self. > >> What do you think about using a coroutine to handle state, how would you >> do it better in a callback based system. > > Without seeing how you are doing it we can't comment on *better*. > We need a baseline. Your approach may be brilliant, or it may > be awful, we can't tell. Yeah probably not brilliant. More like hopefully not completely stupid. > > But remember that there is no such thing as the perfect paradigm. > FP has many strengths but it has many weaknesses too. As does OOP. > Even procedural programming has advantages over OOP and FP in > some circumstances. By all means learn the paradigms, but don't get hung > up on any one. They all play a part. Agreed. I am still trying to learn the right mixture. The GUI is Kivy, but I could probably apply the same concept to QT. Example of my Abused coroutine: def coroutine(func): # A decorator function that takes care of starting a coroutine # automatically on call. def start(*args, **kwargs): cr = func(*args, **kwargs) cr.send(None) return cr return start @coroutine def app_state(APP): # APP = kivy.app.App.get_running_app() # So you know what APP is. while True: signal = yield # Pass if signal is None or less than 1. if signal >= 0 and signal < 1: pass # Ignore this range elif signal >= 1 and signal < 2: if signal == 1.01: # Load Main Menu print('Load File for Displaying Main Menu') # This acts as a callback with the benefit of yielding # to Kivy's main loop. kivy.clock.Clock.schedule_once(APP.signal, 0) yield 1.02 print('Add Main Menu to ScreenManager.') kivy.clock.Clock.schedule_once(APP.signal, 0) yield 1.03 print('Start Music for Main Menu') # Other clean up that I do here. # Remove Game from Screen Manager # Delete References to Game elif signal >= 2 and signal < 3: if signal == 2.01: print('Load File for Displaying Game') kivy.clock.Clock.schedule_once(APP.signal, 0) yield 2.02 print('Add Game to ScreenManager.') kivy.clock.Clock.schedule_once(APP.signal, 0) yield 2.03 print('Start Music for Main Menu') # Other clean up that I do here. # Remove Main Menu from Screen Manager # Delete References to Main Menu state = app_state(kivy.app.App.get_running_app()) kivy.app.App.get_running_app().signal = state.send From danny.yoo at gmail.com Thu Apr 2 21:31:11 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Thu, 2 Apr 2015 12:31:11 -0700 Subject: [Tutor] New to Programming: TypeError: coercing to Unicode: need string or buffer, list found In-Reply-To: References: Message-ID: On Thu, Apr 2, 2015 at 12:19 PM, Saran Ahluwalia wrote: > Danny, > > You were spot on with that issue. I debugged this. Here are my two commits > for my homework: Starting with pyinotify and OS agnostic? I am still working > on the latter - in regards to adding more customization that fits the > homework specifications. As a high-level thing: when you see an error message, do not automatically assume the error message knows the proper remediation. Revisit the error message and your initial instincts: ##################################################################### TypeError: coercing to Unicode: need string or buffer, list found" > I understand this error message when I run this code. However, I am curious > to know what the most pythonic way is to convert the list to a string? ##################################################################### And in retrospect, hopefully you'll see that the correct thing to do was something other than what you thought at first. In programming, when things go wrong, they can go wrong for several different reasons. There is research that suggests that beginners often misinterpret a course of actions when reading error messages. http://gmarceau.qc.ca/papers/Marceau-2010-Measuring-Effectiveness.pdf So try to avoid the temptation to only do something that makes the computer happy. Revisit assumptions. Good luck! From wolfrage8765 at gmail.com Thu Apr 2 21:36:17 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Thu, 02 Apr 2015 15:36:17 -0400 Subject: [Tutor] Functional Programming in Python In-Reply-To: <20150402180712.GY25453@ando.pearwood.info> References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> Message-ID: <551D9A31.3040509@gmail.com> On 04/02/2015 02:07 PM, Steven D'Aprano wrote: >> What are the best practices to create more Functional Python? > > Best practices: > > * Don't force your code to use one style exclusively. Use the most > natural style for the task. Python makes it easy to mix functional, > procedural, imperative and object oriented code in the one > application. Use whatever is most natural for your task. Good point, but still trying to understand how this is best determined beyond trial and error, and to make sure that my assumptions are correct about this decision. > > * Where possible, write your functions and methods in a functional > style. That means: > > - Avoid global variables. I have got this down. > > - Avoid side-effects where possible. Now getting better at this. > > - Separate the logic of your algorithm from the display of results (e.g. > don't have a method that calculates a result AND prints it; have the > method calculate the result, and then have the caller print it). Need to always do this and do it first rather than during re-factoring. > > > - Many uses of map() and filter() are better written as generator > expressions; e.g. instead of: I now understand generators and I am now using them whenever I see the opportunity. > > filter(lambda s: s.lower().startswith("a"), map(str, mylist)) > > you can use: > > (str(x) for x in mylist if s.lower().startswith("a")) > > > - Where useful, write your code to take advantage of "pipelining" > style, e.g. using lazy iterators rather than lists. You can then chain > iterators together to get the desired result. Yes I have started to do this since seeing the power of pipe-lining. > What do you mean? Can you show an example? I added an example in the reply to Alan. From wolfrage8765 at gmail.com Thu Apr 2 21:39:24 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Thu, 02 Apr 2015 15:39:24 -0400 Subject: [Tutor] Functional Programming in Python In-Reply-To: References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> Message-ID: <551D9AEC.3050108@gmail.com> On 04/02/2015 02:52 PM, Danny Yoo wrote: > This is not to say that closures are bad. It's just to point out that > just because functional programs use closures quite a lot, doesn't > automatically mean closures are the most appropriate tool for > everything. If there are parts of the language that already do the > sort of thing you're trying to accomplish, it might be good to reuse > those parts, rather than reinvent the universe. I agree that closures are not the best tool for every job. And in the case of a callback based GUI they simply do not work, since execution needs to leave a function in order to run the GUI's main loop. Thus I abused a coroutine. From wolfrage8765 at gmail.com Thu Apr 2 21:40:28 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Thu, 02 Apr 2015 15:40:28 -0400 Subject: [Tutor] Functional Programming in Python In-Reply-To: <20150402190827.GA5392@mail.akwebsoft.com> References: <551D6BD4.8030507@gmail.com> <20150402190827.GA5392@mail.akwebsoft.com> Message-ID: <551D9B2C.8080401@gmail.com> On 04/02/2015 03:08 PM, Tim Johnson wrote: > You have already received valuable replies from two advanced > python experts. > If you are looking for a book (available digitally for kindle) > I would recommend > Guide To: Functional Python & Comprehension Constructs > by Matt Harrison Thanks I will look into this book. I have been reading a lot of articles on the topic lately. From fomcl at yahoo.com Thu Apr 2 21:49:45 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Thu, 2 Apr 2015 12:49:45 -0700 Subject: [Tutor] Request review: A DSL for scraping a web page Message-ID: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> ----------------------------- On Thu, Apr 2, 2015 1:17 PM CEST Alan Gauld wrote: >On 02/04/15 12:09, Dave Angel wrote: > >> Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls >> books, and have a trip down memory lane. I bet 95% of those are still >> useful, even if they refer to much earlier versions of language(s). > >Yes, the Pearls books should be required reading for all new programmers. The lessons are pretty timeless, it's only the >languages that change - and most of his examples seem to be >in a kind of pseudo Pascal dialect rather than real code anyway. > >I believe they've been re-released as a single volume now. Is this the book you are referring to? http://www.amazon.com/Programming-Pearls-2nd-Edition-Bentley/dp/0201657880 Thanks! From davea at davea.name Thu Apr 2 22:18:52 2015 From: davea at davea.name (Dave Angel) Date: Thu, 02 Apr 2015 16:18:52 -0400 Subject: [Tutor] New to Programming: TypeError: coercing to Unicode: need string or buffer, list found In-Reply-To: References: Message-ID: <551DA42C.4040302@davea.name> On 04/02/2015 08:28 AM, Saran Ahluwalia wrote: > Good Morning: > > I understand this error message when I run this code. However, I am curious > to know what the most pythonic way is to convert the list to a string? I > use Python 2.7. > > "Traceback (most recent call last): > before = dict([(f, None) for f in os.listdir(dirlist)]) > TypeError: coercing to Unicode: need string or buffer, list found" > > > The sample code that I am trying to run is: > > path = "/Users/Desktop/Projects/" > dirlist = os.listdir(path) > before = dict([(f, None) for f in os.listdir(dirlist)]) You have two calls to listdir in the code you quote here. Once you've called os.listdir(path) you get back a list of filenames. Why you then call os.listdir again on that list I have no clue. And I also have no idea what you think the dict is going to do. > > def main(dirlist): > while True: > time.sleep(10) #time between update check > after = dict([(f, None) for f in os.listdir(dirlist)]) > added = [f for f in after if not f in before] > if added: > print('Successfully added new file - ready to validate') > if __name__ == "__main__": > main() You didn't run that code, as this call to main() passes no arguments. Last time I saw your whole file, it had two separate if __name__ == "__main__" clauses. So you'd better make sure one of them is commented out, or it'll keep confusing you. First thing is to pick better names. And second is to add a comment to each function as to what it expects for arguments. main() expects a directory name, so rename the dirlist variable to something like path. Then figure out what the argument to main() should look like. it should not be sys.argv[1:], as that's a list. You want a single item on the command line specifying the path. This whole thing with 'before' and 'after' is the long way around. Since you're going to move files from this directory after you analyze them, all you need to do is call os.listdir again each time through the loop. Anything you find will be new, by definition. Then once you have your list, you do NOT want to loop through it, as you're going to be calling a function (already written by you) that wants a list of filenames. Incidentally you posted some code earlier, in yet another new thread, that calls copyfile() from the function move_to_failure_folder(). Shouldn't that function be called movefile()? and shouldn't it use a different shutil function? -- DaveA From davea at davea.name Thu Apr 2 22:42:56 2015 From: davea at davea.name (Dave Angel) Date: Thu, 02 Apr 2015 16:42:56 -0400 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> References: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: <551DA9D0.4010802@davea.name> On 04/02/2015 03:49 PM, Albert-Jan Roskam wrote: > > ----------------------------- > On Thu, Apr 2, 2015 1:17 PM CEST Alan Gauld wrote: > >> On 02/04/15 12:09, Dave Angel wrote: >> >>> Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls >>> books, and have a trip down memory lane. I bet 95% of those are still >>> useful, even if they refer to much earlier versions of language(s). >> >> Yes, the Pearls books should be required reading for all new programmers. The lessons are pretty timeless, it's only the >> languages that change - and most of his examples seem to be >> in a kind of pseudo Pascal dialect rather than real code anyway. >> >> I believe they've been re-released as a single volume now. > > Is this the book you are referring to? > http://www.amazon.com/Programming-Pearls-2nd-Edition-Bentley/dp/0201657880 > > Thanks! That is a new edition of "Programming Pearls", but I can't tell from its description if it also includes "More Programming Pearls: Confessions of a Coder" If the two were merged, I don't spot it any place on Amazon. -- DaveA From alan.gauld at btinternet.com Thu Apr 2 23:02:51 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 02 Apr 2015 22:02:51 +0100 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> References: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: <551DAE7B.3010803@btinternet.com> On 02/04/15 20:49, Albert-Jan Roskam wrote: > Yes, the Pearls books should be required reading > Is this the book you are referring to? > http://www.amazon.com/Programming-Pearls-2nd-Edition-Bentley/dp/0201657880 > Yes thats it. > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > From ahlusar.ahluwalia at gmail.com Thu Apr 2 21:19:55 2015 From: ahlusar.ahluwalia at gmail.com (Saran Ahluwalia) Date: Thu, 2 Apr 2015 15:19:55 -0400 Subject: [Tutor] New to Programming: TypeError: coercing to Unicode: need string or buffer, list found In-Reply-To: References: Message-ID: Danny, You were spot on with that issue. I debugged this. Here are my two commits for my homework: Starting with pyinotify and OS agnostic? I am still working on the latter - in regards to adding more customization that fits the homework specifications. Feel free to shoot me any critical feedback - when you can. Cheers: Saran On Thu, Apr 2, 2015 at 1:45 PM, Danny Yoo wrote: > > On Apr 2, 2015 9:45 AM, "Saran Ahluwalia" > wrote: > > > > Good Morning: > > > > I understand this error message when I run this code. However, I am > curious > > to know what the most pythonic way is to convert the list to a string? I > > use Python 2.7. > > > > "Traceback (most recent call last): > > before = dict([(f, None) for f in os.listdir(dirlist)]) > > TypeError: coercing to Unicode: need string or buffer, list found" > > I actually do not understand the error. :p > > In particular, I do not understand the subexpression: > > os.listdir(dirlist) > > Can you explain what you are trying to do there? The listdir function > only consumes single strings, so this looks like a mistake unless dirlist > is a string. > From tim at akwebsoft.com Fri Apr 3 02:10:44 2015 From: tim at akwebsoft.com (Tim Johnson) Date: Thu, 2 Apr 2015 16:10:44 -0800 Subject: [Tutor] Functional Programming in Python In-Reply-To: <551D9B2C.8080401@gmail.com> References: <551D6BD4.8030507@gmail.com> <20150402190827.GA5392@mail.akwebsoft.com> <551D9B2C.8080401@gmail.com> Message-ID: <20150403001044.GA1757@mail.akwebsoft.com> * WolfRage [150402 11:45]: > On 04/02/2015 03:08 PM, Tim Johnson wrote: > > > You have already received valuable replies from two advanced > > python experts. > > If you are looking for a book (available digitally for kindle) > > I would recommend > > Guide To: Functional Python & Comprehension Constructs > > by Matt Harrison > Thanks I will look into this book. I have been reading a lot of articles > on the topic lately. Harrison really focuses on List Comprehension as the idiomatic pythonist approach. He's very clear and concise as this eternal noob can readily understand him. I hope you find it edifying. -- Tim tim at tee jay forty nine dot com or akwebsoft dot com http://www.akwebsoft.com, http://www.tj49.com From jnl_public at yahoo.com Fri Apr 3 01:02:26 2015 From: jnl_public at yahoo.com (J L) Date: Thu, 2 Apr 2015 23:02:26 +0000 (UTC) Subject: [Tutor] Command Line Editting: How to improve options? In-Reply-To: <20150402120751.GX25453@ando.pearwood.info> References: <20150402120751.GX25453@ando.pearwood.info> Message-ID: <1595076443.4131028.1428015746150.JavaMail.yahoo@mail.yahoo.com> Thank you Steve.? This electronic mail including any attachments may contain information that is privileged, confidential, and/or otherwise protected from disclosure to anyone other than its intended recipient(s). Any dissemination of this electronic email or its contents including any attachments is prohibited without prior consent. On Thursday, April 2, 2015 5:09 AM, Steven D'Aprano wrote: On Thu, Apr 02, 2015 at 06:36:03AM +0000, J L wrote: > ?Win 7Python v 3.4.3 > I'm new to Python and only have coursework under my belt in another > object oriented programming language as well as limited systems > skills. After launching Python?from the command line with py.exe, it > appears that the interrupter starts up fine. I've read on Python.Org's > site in a tutorial section that some interrupters offer command line > editing beyond simple use of the arrow keys and backspace. It does not > appear that my environment is allowing these greater abilities. How > does one afford increased abilities to edit commands within Python's > interrupter? Thank you. Sadly, Windows does not offer much in the way of powerful interactive commands like most Linux shells do. You can try these options: - try using Python's IDLE: http://www.google.com.au/search?q=how+to+run+IDLE+python - Use a commercial third-party IDE ("Integrated Development Environment") such as PyCharm, Anaconda or Komodo. Some of them may cost money, but they may have free or trial versions. - Or a third-party editor such as Spyder, if it comes with its own interactive shell. - I can strongly recomment iPython, which is very powerful and includes a lot of command-line features that even Linux shells don't: http://ipython.org/ ? If you've used Mathematica, you may love iPython's "notepad" feature. Now we start getting to slightly more complex options, which may not work, but it would be interesting to try: - Try installing pyreadline, and see it is will work with Python 3.4. If it does, you might be able to convince Python 3.4's rlcompleter module to work with it. - Still if pyreadline works with Python 3.4, you might like my command line tab completer and history module rather than the built-in one: http://code.google.com/p/tabhistory/source/browse/tabhistory.py I've never tested it on Windows, so I don't know if it will actually work or not. Good luck! -- Steve _______________________________________________ Tutor maillist? -? Tutor at python.org To unsubscribe or change subscription options: https://mail.python.org/mailman/listinfo/tutor From akleider at sonic.net Fri Apr 3 02:29:57 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 02 Apr 2015 17:29:57 -0700 Subject: [Tutor] python3.4m Message-ID: <2a8173b7079ef94a3a08c2203cedd052@sonic.net> A listing of /usr/bin/python* on my Ubuntu 14.04 LTS machine yields the following: alex at t61p:~$ ls -l /usr/bin/python* lrwxrwxrwx 1 root root 9 Aug 23 2014 /usr/bin/python -> python2.7 lrwxrwxrwx 1 root root 9 Aug 23 2014 /usr/bin/python2 -> python2.7 -rwxr-xr-x 1 root root 3176896 Mar 22 2014 /usr/bin/python2.7 lrwxrwxrwx 1 root root 9 Aug 23 2014 /usr/bin/python3 -> python3.4 -rwxr-xr-x 1 root root 3802224 Apr 11 2014 /usr/bin/python3.4 -rwxr-xr-x 1 root root 3802224 Apr 11 2014 /usr/bin/python3.4m lrwxrwxrwx 1 root root 10 Aug 23 2014 /usr/bin/python3m -> python3.4m What is python3.4m? When might one want it instead of python3.4 without the 'm'? thanks, Alex From ben+python at benfinney.id.au Fri Apr 3 04:42:31 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Fri, 03 Apr 2015 13:42:31 +1100 Subject: [Tutor] python3.4m References: <2a8173b7079ef94a3a08c2203cedd052@sonic.net> Message-ID: <85fv8i0w6g.fsf@benfinney.id.au> Alex Kleider writes: > A listing of /usr/bin/python* on my Ubuntu 14.04 LTS machine yields > the following: > alex at t61p:~$ ls -l /usr/bin/python* > [?] > -rwxr-xr-x 1 root root 3802224 Apr 11 2014 /usr/bin/python3.4m > lrwxrwxrwx 1 root root 10 Aug 23 2014 /usr/bin/python3m -> > python3.4m > > What is python3.4m? I can't tell you what it is. I can, though, tell you how to query what package installed it:: $ dpkg --search /usr/bin/python3.4m which might give some useful information. -- \ ?Whenever you read a good book, it's like the author is right | `\ there, in the room talking to you, which is why I don't like to | _o__) read good books.? ?Jack Handey | Ben Finney From steve at pearwood.info Fri Apr 3 05:23:31 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 3 Apr 2015 14:23:31 +1100 Subject: [Tutor] Functional Programming in Python In-Reply-To: <551D9A31.3040509@gmail.com> References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> <551D9A31.3040509@gmail.com> Message-ID: <20150403032331.GB25453@ando.pearwood.info> On Thu, Apr 02, 2015 at 03:36:17PM -0400, WolfRage wrote: > On 04/02/2015 02:07 PM, Steven D'Aprano wrote: > > >>What are the best practices to create more Functional Python? > > > >Best practices: > > > >* Don't force your code to use one style exclusively. Use the most > > natural style for the task. Python makes it easy to mix functional, > > procedural, imperative and object oriented code in the one > > application. Use whatever is most natural for your task. > > Good point, but still trying to understand how this is best determined > beyond trial and error, and to make sure that my assumptions are correct > about this decision. Practice and experience! > >* Where possible, write your functions and methods in a functional > > style. That means: > > > >- Avoid global variables. > > I have got this down. Just for the record, not all use of globals is bad. In my previous reply to Danny, I gave an example of "late binding" for a default parameter. In general, global constants, or near constants (e.g. you write to the variable once when your application starts up, perhaps after reading the value from a config file) are acceptable. > >- Avoid side-effects where possible. > > Now getting better at this. In object-oriented code, "side-effects" of course refers to side-effects outside of the object itself. An object is allowed to manipulate its own state. However, even in OO code, it is very useful to avoid side-effects. For example, the object might be immutable, so once it is initialised it cannot be changed. Even if your object is mutable, you should cleanly separate mutator methods which can modify the object from side-effect free methods which do not. E.g. it is okay for list.sort() to mutate the list, but list.index() should not! -- Steve From steve at pearwood.info Fri Apr 3 05:07:02 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 3 Apr 2015 14:07:02 +1100 Subject: [Tutor] Functional Programming in Python In-Reply-To: References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> Message-ID: <20150403030702.GA25453@ando.pearwood.info> On Thu, Apr 02, 2015 at 11:52:40AM -0700, Danny Yoo wrote: > >> What are your thoughts on Functional in Python? > >> Currently I am re-writing functions to reduce their side effects. > >> I am also removing the state from objects and putting it into a closure > >> type function. > > > > That doesn't remove state, it just moves it to a different place. > > > > However, encapsulating state inside a closure, or an object, it often > > the most effective and natural way to deal with a problem. Better than > > passing around long and confusing numbers of variables! > > Theoretically, I'd agree with this. But engineering-wise, I'd > recommend explicit structures or objects if possible when representing > state. Yes, I agree! Hence my comment about encapsulating state inside a closure *or an object* rather than keeping your application state in your head, passing around vast numbers of variables only because some other part of your application needs them... [...] > Let's make this concrete. If we want to represent a coordinate, a > pair of numbers, we could use raw closures for this... > > ################################ > def pair(x, y): > def dispatch(msg): > if msg == 'x': > return x > if msg == 'y': > return y > return dispatch > > p = pair(3, 4) > print p('x') > print p('y') > ################################ > > And this works! > > > But there's already a feature in the language that does this kind of > aggregation. > > ################################ > class pair(object): > def __init__(self, x, y): > self.x, self.y = x, y > > p = pair(3, 4) > print p.x > print p.y > ################################# > > This is something that folks expect and is well supported and understood. Precisely. I was thinking more along the idea of using closures, or functools.partial, for encapsulating state in this way. Suppose we start with two global variables: def greet(): print "%s, %s!" % (greeting, name) greeting = "Salutations" name = "Danny" greet() Yuck. The obvious fix is to turn the globals into parameters: def greet(greeting, name): print "%s, %s!" % (greeting, name) and pass in the greeting and name you need. And for many purposes that is exactly the solution you need. But... sometimes you don't want to have to manually keep track of this "greeting" variable just for the sake of passing it on to the greet() function. There are lots of solutions to that problem: # Early binding default value. def greet(name, greeting="Salutations"): print "%s, %s!" % (greeting, name) # Late binding default value. GREETING = "Salutations" def greet(name, greeting=None): if greeting is None: greeting = GREETING print "%s, %s!" % (greeting, name) # An object is overkill, but let's do it anyway class Greeter: def __init__(self, greeting): self.greeting = greeting def greet(self, name): print "%s, %s!" % (self.greeting, name) mygreeter = Greeter("Salutations") mygreeter.greet("Danny") Or we can use a closure: def make_greeter(greeting): def greet(name): print "%s, %s!" % (greeting, name) return greet greet = make_greeter("Salutations") greet("Danny") > This is not to say that closures are bad. It's just to point out that > just because functional programs use closures quite a lot, doesn't > automatically mean closures are the most appropriate tool for > everything. If there are parts of the language that already do the > sort of thing you're trying to accomplish, it might be good to reuse > those parts, rather than reinvent the universe. Agreed. That's the beauty of Python: you can mix paradigms in the one piece of code. The downside of this is that it reduces the opportunities for many compile-time optimizations (e.g. the compiler cannot know for sure that any function is free of side-effects) but that's often an acceptable price to pay. -- Steve From akleider at sonic.net Fri Apr 3 06:35:49 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 02 Apr 2015 21:35:49 -0700 Subject: [Tutor] python3.4m In-Reply-To: <85fv8i0w6g.fsf@benfinney.id.au> References: <2a8173b7079ef94a3a08c2203cedd052@sonic.net> <85fv8i0w6g.fsf@benfinney.id.au> Message-ID: On 2015-04-02 19:42, Ben Finney wrote: > Alex Kleider writes: > >> A listing of /usr/bin/python* on my Ubuntu 14.04 LTS machine yields >> the following: >> alex at t61p:~$ ls -l /usr/bin/python* >> [?] >> -rwxr-xr-x 1 root root 3802224 Apr 11 2014 /usr/bin/python3.4m >> lrwxrwxrwx 1 root root 10 Aug 23 2014 /usr/bin/python3m -> >> python3.4m >> >> What is python3.4m? > > I can't tell you what it is. I can, though, tell you how to query what > package installed it:: > > $ dpkg --search /usr/bin/python3.4m > > which might give some useful information. It does indeed: alex at t61p:~$ dpkg --search /usr/bin/python3.4m python3.4-minimal: /usr/bin/python3.4m This elaborates a bit: https://launchpad.net/ubuntu/trusty/+package/python3.4-minimal Thanks for the tip. ak From rajbirs799 at gmail.com Fri Apr 3 05:58:28 2015 From: rajbirs799 at gmail.com (Rajbir Singh) Date: Fri, 3 Apr 2015 09:28:28 +0530 Subject: [Tutor] Command Line Editting: How to improve options? In-Reply-To: <1595076443.4131028.1428015746150.JavaMail.yahoo@mail.yahoo.com> References: <20150402120751.GX25453@ando.pearwood.info> <1595076443.4131028.1428015746150.JavaMail.yahoo@mail.yahoo.com> Message-ID: pycharm is IDE for python, ive been using it for a while now, compiles python script, works as a text editor, allows downloading third party libs, so far i havnt found anything that i need as python coder and it doesnt have!! give it a try -- "PyCharm" On Fri, Apr 3, 2015 at 4:32 AM, J L wrote: > Thank you Steve. > > > This electronic mail including any attachments may contain information > that is privileged, confidential, and/or otherwise protected from > disclosure to anyone other than its intended recipient(s). Any > dissemination of this electronic email or its contents including any > attachments is prohibited without prior consent. > > > > On Thursday, April 2, 2015 5:09 AM, Steven D'Aprano < > steve at pearwood.info> wrote: > > > On Thu, Apr 02, 2015 at 06:36:03AM +0000, J L wrote: > > Win 7Python v 3.4.3 > > I'm new to Python and only have coursework under my belt in another > > object oriented programming language as well as limited systems > > skills. After launching Python from the command line with py.exe, it > > appears that the interrupter starts up fine. I've read on Python.Org's > > site in a tutorial section that some interrupters offer command line > > editing beyond simple use of the arrow keys and backspace. It does not > > appear that my environment is allowing these greater abilities. How > > does one afford increased abilities to edit commands within Python's > > interrupter? Thank you. > > > Sadly, Windows does not offer much in the way of powerful interactive > commands like most Linux shells do. You can try these options: > > - try using Python's IDLE: > > http://www.google.com.au/search?q=how+to+run+IDLE+python > > - Use a commercial third-party IDE ("Integrated Development > Environment") such as PyCharm, Anaconda or Komodo. Some of them may cost > money, but they may have free or trial versions. > > - Or a third-party editor such as Spyder, if it comes with its own > interactive shell. > > - I can strongly recomment iPython, which is very powerful and includes > a lot of command-line features that even Linux shells don't: > > http://ipython.org/ > ? > If you've used Mathematica, you may love iPython's "notepad" feature. > > Now we start getting to slightly more complex options, which may not > work, but it would be interesting to try: > > - Try installing pyreadline, and see it is will work with Python 3.4. If > it does, you might be able to convince Python 3.4's rlcompleter module > to work with it. > > - Still if pyreadline works with Python 3.4, you might like my command > line tab completer and history module rather than the built-in one: > > http://code.google.com/p/tabhistory/source/browse/tabhistory.py > > I've never tested it on Windows, so I don't know if it will actually > work or not. > > > Good luck! > > > > -- > Steve > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From joe.farro at gmail.com Sat Apr 4 11:42:39 2015 From: joe.farro at gmail.com (Joe Farro) Date: Sat, 4 Apr 2015 09:42:39 +0000 (UTC) Subject: [Tutor] Request review: A DSL for scraping a web page References: Message-ID: Joe Farro gmail.com> writes: > > Thanks, Peter. > > Peter Otten <__peter__ web.de> writes: > > > Can you give a real-world example where your DSL is significantly cleaner > > than the corresponding code using bs4, or lxml.xpath, or lxml.objectify? Peter, I worked up what I hope is a fairly representative example. It scrapes metadata from the 10 newest web-scraping questions on stackoverflow. It's done with bs4 and take. https://github.com/tiffon/take-examples/tree/master/samples/stackoverflow I've posted on the bs4 discussion group asking for feedback on the bs4 version to make sure it's up to snuff. (The post is in new-member purgatory, at the moment.) In my opinion, the fact that take lacks an ability to define sub-routines is a brutal deficiency. (As compared to defining functions like `get_poster_details()` and `get_comment_activity()` in the bs4 version.) On the bright side, I do like that the indentation of the take templates semi-reflect the structure of the HTML document. However, the indentation doesn't (always) reflect the hierarchy of the data being generated, which seems more clear. Feedback is definitely welcome. Thanks again! From joe.farro at gmail.com Sat Apr 4 18:24:10 2015 From: joe.farro at gmail.com (Joe Farro) Date: Sat, 4 Apr 2015 16:24:10 +0000 (UTC) Subject: [Tutor] Request review: A DSL for scraping a web page References: Message-ID: Joe Farro gmail.com> writes: > indentation doesn't (always) reflect the hierarchy of the data being > generated, which seems more clear. Meant to say: However, the indentation doesn't (always) reflect the hierarchy of the data being generated, which seems more clear **in the bs4 version**. From robertvstepp at gmail.com Sat Apr 4 18:49:08 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 4 Apr 2015 11:49:08 -0500 Subject: [Tutor] Use of "or" in a lambda expression Message-ID: Windows 7, Python 3.4.3 This code snippet is "Example 7-13" on page 383 from "Programming Python, 4th ed." by Mark Lutz : import sys from tkinter import * widget = Button(None, text='Hello event world!', command=(lambda: print('Hello lambda world!') or sys.exit())) widget.pack() widget.mainloop() My question is about the lambda expression. The author states "...this version uses an or operator to force two expressions to be run..." I am not understanding how 'or' causes this to happen. I guess I am expecting the 'or' to result only in the print running without executing sys.exit(). But that is not what happens--of course. I tried substituting 'and' for 'or', but this results in only the print being run! Obviously I have a significant misunderstanding of what is going on. Thanks! -- boB From steve at pearwood.info Sat Apr 4 19:34:11 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 5 Apr 2015 03:34:11 +1000 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: <20150404173408.GJ25453@ando.pearwood.info> On Sat, Apr 04, 2015 at 11:49:08AM -0500, boB Stepp wrote: > Windows 7, Python 3.4.3 > > This code snippet is "Example 7-13" on page 383 from "Programming > Python, 4th ed." by Mark Lutz : > > import sys > from tkinter import * > > widget = Button(None, > text='Hello event world!', > command=(lambda: print('Hello lambda world!') or sys.exit())) o_O That's either the most horrible misuse of lambda I've ever seen, or a really cool and rather nifty trick. I'm not sure which :-) > widget.pack() > widget.mainloop() > > My question is about the lambda expression. The author states "...this > version uses an or operator to force two expressions to be run..." I > am not understanding how 'or' causes this to happen. I guess I am > expecting the 'or' to result only in the print running without > executing sys.exit(). But that is not what happens--of course. I tried > substituting 'and' for 'or', but this results in only the print being > run! Obviously I have a significant misunderstanding of what is going > on. Both `or` and `and` are "short-circuit" operators. Here is a truth-table for `a or b`: |a = True False -----------+----------------- b = True | True True False | True False If `a` is true, then `a or b` is true, regardless of whether b is true or false. So we can say that if `a` is true, `a or b` returns `a`. If `a` is false, then `a or b` returns true if, and only if, `b` is true; otherwise it returns false. So we can say that if `a` is false, then `a or b` returns `b`. So we can define our own "or" function like this: def or_ (a, b): if a: return a else: return b Unlike this function version, the `or` operator doesn't evaluate the `b` expression unless needed. So this piece of code: print(msg) or sys.exit() runs like this: (1) Evaluate the expression on the left of the operator: print(msg). (2) That has the side-effect of printing the message, and returns the value None. (3) Is None a true value? If so, `or` can short-circuit, and return it as its result. (4) But None is a false value, so evaluate the expression on the right of the operator: sys.exit() (5) Which has the side-effect of exiting the interpreter. (6) The `or` operator would now return the result of sys.exit(), if it had one; but it doesn't, since the interpreter has just exited. A cleaner example might be this: py> def true(): ... print("calling true") ... return 23 # a true-ish value ... py> def false(): ... print("calling false") ... return 0 # a false-ish value ... py> true() or false() # only the left operand is evaluated calling true 23 py> true() or true() calling true 23 py> false() or true() # both operands are evaluated calling false calling true 23 py> false() or false() calling false calling false 0 The `and` operator is similar, except the truth-table looks like this: |a = True False -----------+----------------- b = True | True False False | False False Again, the right-hand operand is only evaluated if it is needed. This lets us write code like this: if mylist and mylist[0] == spam: eggs() If mylist is empty, then `mylist and ...` doesn't even need to evaluate the right-hand operand, mylist[0] doesn't run and so does not fail. Only if mylist is a truthy value does mylist[0] run. -- Steve From robertvstepp at gmail.com Sat Apr 4 20:06:59 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 4 Apr 2015 13:06:59 -0500 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: <20150404173408.GJ25453@ando.pearwood.info> References: <20150404173408.GJ25453@ando.pearwood.info> Message-ID: On Sat, Apr 4, 2015 at 12:34 PM, Steven D'Aprano wrote: > On Sat, Apr 04, 2015 at 11:49:08AM -0500, boB Stepp wrote: >> Windows 7, Python 3.4.3 >> >> This code snippet is "Example 7-13" on page 383 from "Programming >> Python, 4th ed." by Mark Lutz : >> >> import sys >> from tkinter import * >> >> widget = Button(None, >> text='Hello event world!', >> command=(lambda: print('Hello lambda world!') or sys.exit())) > > o_O > > That's either the most horrible misuse of lambda I've ever seen, or a > really cool and rather nifty trick. I'm not sure which :-) Now that I have read (and hopefully understand) your entire response, I am wondering the same thing in the sense that my understanding of Python's intent is for clearly readable code and this usage isn't clear without some thought (At least for me!). >> widget.pack() >> widget.mainloop() >> >> My question is about the lambda expression. The author states "...this >> version uses an or operator to force two expressions to be run..." I >> am not understanding how 'or' causes this to happen. I guess I am >> expecting the 'or' to result only in the print running without >> executing sys.exit(). But that is not what happens--of course. I tried >> substituting 'and' for 'or', but this results in only the print being >> run! Obviously I have a significant misunderstanding of what is going >> on. > > > Both `or` and `and` are "short-circuit" operators. Here is a truth-table I get and understand the short-circuit logic. This isn't what got me! [...] > expression unless needed. So this piece of code: > > print(msg) or sys.exit() > > runs like this: > > (1) Evaluate the expression on the left of the operator: print(msg). > (2) That has the side-effect of printing the message, and returns > the value None. This was my 'gotcha'. I forgot (but knew) that print functions return None. Perhaps this constant switching back and forth between using Python 2 at work and Python 3 at home is addling my brain? Also, even if I had recalled the return of None, I might have missed that the "side-effect" still occurs, i.e., the actual printing. [...] > The `and` operator is similar, except the truth-table looks like this: > > > |a = True False > -----------+----------------- > b = True | True False > False | False False And of course since print returns None, the short-circuit evaluation causes the sys.exit() never to be seen. Even though I snipped out most of your very well-constructed examples, Steve, I have to say, you have a knack for making things abundantly clear! You tutor very well, indeed, and I am appreciative! -- boB From robertvstepp at gmail.com Sat Apr 4 21:21:19 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 4 Apr 2015 14:21:19 -0500 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: <20150404173408.GJ25453@ando.pearwood.info> References: <20150404173408.GJ25453@ando.pearwood.info> Message-ID: On Sat, Apr 4, 2015 at 12:34 PM, Steven D'Aprano wrote: > On Sat, Apr 04, 2015 at 11:49:08AM -0500, boB Stepp wrote: >> Windows 7, Python 3.4.3 >> >> This code snippet is "Example 7-13" on page 383 from "Programming >> Python, 4th ed." by Mark Lutz : >> >> import sys >> from tkinter import * >> >> widget = Button(None, >> text='Hello event world!', >> command=(lambda: print('Hello lambda world!') or sys.exit())) > > o_O > > That's either the most horrible misuse of lambda I've ever seen, or a > really cool and rather nifty trick. I'm not sure which :-) Re-reading the paragraph relevant to Mr. Lutz's example, perhaps I should quote the full paragraph: "This code is a bit tricky because lambdas can contain only an expression; to emulate the original script, this version uses an or operator to force two expressions to be run (print works as the first, because it's a function call in Python 3.X--we don't need to resort to using sys.stdout directly)." I think the key thought of the author here is he showing how to rewrite an earlier example that explicitly defines a quit() function, which both prints and then exits the program, to using a lambda expression. I don't think his intent is to say that the lambda expression is to be preferred (Or is he?). To my mind, would: def quit(): print('Hello lambda world!') sys.exit() and: widget = Button(None, text='Hello event world!', command=quit) be preferable Python style? boB From robertvstepp at gmail.com Sat Apr 4 21:32:25 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 4 Apr 2015 14:32:25 -0500 Subject: [Tutor] Request review: A DSL for scraping a web page In-Reply-To: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> References: <1428004185.39042.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On Thu, Apr 2, 2015 at 2:49 PM, Albert-Jan Roskam wrote: > > ----------------------------- > On Thu, Apr 2, 2015 1:17 PM CEST Alan Gauld wrote: > >>On 02/04/15 12:09, Dave Angel wrote: >> >>> Ah, Jon Bentley (notice the extra 'e'). I should dig out my *Pearls >>> books, and have a trip down memory lane. I bet 95% of those are still >>> useful, even if they refer to much earlier versions of language(s). >> >>Yes, the Pearls books should be required reading for all new programmers. The lessons are pretty timeless, it's only the >>languages that change - and most of his examples seem to be >>in a kind of pseudo Pascal dialect rather than real code anyway. >> >>I believe they've been re-released as a single volume now. > > Is this the book you are referring to? > http://www.amazon.com/Programming-Pearls-2nd-Edition-Bentley/dp/0201657880 This thread inspired me to order both books from Amazon. The one linked to above by Alan is an expanded and somewhat rewritten edition of the original. It does NOT include "More Programming Pearls". I just today received my copy of "Programming Pearls, 2nd ed." To quote from part of the author's preface of "Programming Pearls, 2nd ed.": "To Readers of the First Edition I hope that your first response as you thumb through this edition of the book is, 'This sure looks familiar.' A few minutes later, I hope that you'll observe, 'I've never seen that before.' This version has the same focus as the first edition, but is set in a larger context. Computing has grown substantially in important areas such as databases, networking and user interfaces. Most programmers should be familiar users of such technologies. At the center of each of those areas, though, is a hard core of programming problems. Those programs remain the theme of this book. This edition of the book is a slightly larger fish in a much larger pond. ..." HTH -- boB From danny.yoo at gmail.com Sat Apr 4 22:10:05 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Sat, 4 Apr 2015 13:10:05 -0700 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: <20150404173408.GJ25453@ando.pearwood.info> Message-ID: > > To my mind, would: > > def quit(): > print('Hello lambda world!') > sys.exit() > > and: > > widget = Button(None, text='Hello event world!', command=quit) > > be preferable Python style? > Yes, I'd prefer this much more, compared to the original. From alan.gauld at btinternet.com Sat Apr 4 22:35:26 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 04 Apr 2015 21:35:26 +0100 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On 04/04/15 17:49, boB Stepp wrote: > widget = Button(None, > text='Hello event world!', > command=(lambda: print('Hello lambda world!') or sys.exit())) > am not understanding how 'or' causes this to happen. I guess I am > expecting the 'or' to result only in the print running without This is explained in more detail in the functional programming topic of my tutorial. It's called short circuit evaluation of boolean expressions if you want to look it up on wikipedia or elsewhere. The short version is that to evaluate an OR Python looks at the first expression and if its true it returns the result - since any single True expression makes the OR true too. If the first expression is false-like (eg None returned from a print() ) then it must evaluate the second expression to be sure of the overall OR result. So by putting a print() which returns None, first Lutz ensures the second expression is also evaluated. He could have done it in various other ways too: eg. lambda : all(print('Hello lambda world!'), sys.exit() ) But the OR style is established as a kind of idiom, not just in Python but several other languages too. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Sat Apr 4 23:57:05 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 4 Apr 2015 16:57:05 -0500 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld wrote: > He could have done it in various other ways too: > > eg. > lambda : all(print('Hello lambda world!'), sys.exit() ) Is this what you meant? Because print will always return False. Or did you actually mean: lambda: any(print('Hello lambda world!'), sys.exit()) > But the OR style is established as a kind of idiom, > not just in Python but several other languages too. So this is not unusual for Python. BTW, what are some of the other languages where this type of expression might be commonly used? -- boB From davea at davea.name Sun Apr 5 00:40:42 2015 From: davea at davea.name (Dave Angel) Date: Sat, 04 Apr 2015 18:40:42 -0400 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: <5520686A.1010106@davea.name> On 04/04/2015 05:57 PM, boB Stepp wrote: > On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld wrote: >> He could have done it in various other ways too: >> >> eg. >> lambda : all(print('Hello lambda world!'), sys.exit() ) > > Is this what you meant? Because print will always return False. Or did > you actually mean: > > lambda: any(print('Hello lambda world!'), sys.exit()) > >> But the OR style is established as a kind of idiom, >> not just in Python but several other languages too. > > So this is not unusual for Python. BTW, what are some of the other > languages where this type of expression might be commonly used? > > I don't think I've ever seen it used in Python. But it's quite common in Perl scripts and bash scripts that I've seen. In the case of bash, one might do something like: prog1 && prog2 and prog2 gets executed only if prog1 had a successful completion -- DaveA From breamoreboy at yahoo.co.uk Sun Apr 5 01:30:10 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Sun, 05 Apr 2015 00:30:10 +0100 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On 04/04/2015 17:49, boB Stepp wrote: > Windows 7, Python 3.4.3 > > This code snippet is "Example 7-13" on page 383 from "Programming > Python, 4th ed." by Mark Lutz : > > import sys > from tkinter import * > > widget = Button(None, > text='Hello event world!', > command=(lambda: print('Hello lambda world!') or sys.exit())) > widget.pack() > widget.mainloop() > > My question is about the lambda expression. The author states "...this > version uses an or operator to force two expressions to be run..." I > am not understanding how 'or' causes this to happen. I guess I am > expecting the 'or' to result only in the print running without > executing sys.exit(). But that is not what happens--of course. I tried > substituting 'and' for 'or', but this results in only the print being > run! Obviously I have a significant misunderstanding of what is going > on. > > Thanks! > The print function in Python 3 always returns None, which is a false value. As we're talking 'or' here the second part wills always get run, hence in this case sys.exit() gets called. I'd try the same thing by using your own function. def myprint(mystr): print(mystr) return 0 Substitute print in the lambda with myprint and try it, then replace the '0' with a '1' and see what happens. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From alan.gauld at btinternet.com Sun Apr 5 01:55:16 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 05 Apr 2015 00:55:16 +0100 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On 04/04/15 22:57, boB Stepp wrote: > On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld wrote: >> He could have done it in various other ways too: >> >> eg. >> lambda : all(print('Hello lambda world!'), sys.exit() ) > > Is this what you meant? Because print will always return False. Or did > you actually mean: > > lambda: any(print('Hello lambda world!'), sys.exit()) any() would be more obvious, but in my interpreter both any() and all() evaluate both functions before testing the results. At least they do once you fix the TypeError : they should be in a list/tuple... lambda : all([print('Hello lambda world!'), sys.exit()] ) > So this is not unusual for Python. BTW, what are some of the other > languages where this type of expression might be commonly used? It's sometimes used in Turbo Pascal/Delphi and also in Perl (a lot!). I think I've seen it used in PHP too. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From wolfrage8765 at gmail.com Sun Apr 5 03:53:28 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Sat, 04 Apr 2015 21:53:28 -0400 Subject: [Tutor] Functional Programming in Python In-Reply-To: <20150403032331.GB25453@ando.pearwood.info> References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> <551D9A31.3040509@gmail.com> <20150403032331.GB25453@ando.pearwood.info> Message-ID: <55209598.7010801@gmail.com> So I was surprised I did not get more feedback on my abused coroutine, maybe that is good or bad, not sure. Any ways I am on to trying to make that coroutine act more like the State Pattern from Gang of Four. And well reading this: http://gameprogrammingpatterns.com/state.html I am not sure how to do this: class Heroine { public: virtual void handleInput(Input input) { state_->handleInput(*this, input); } virtual void update() { state_->update(*this); } // Other methods... private: HeroineState* state_; }; (Pointing to the different classes. Since C++ has virtual methods but Python does not?) in Python? Do I just reference the new method? Because state_ will always be the correct object? From steve at pearwood.info Sun Apr 5 05:11:33 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 5 Apr 2015 13:11:33 +1000 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: <20150404173408.GJ25453@ando.pearwood.info> Message-ID: <20150405031132.GL25453@ando.pearwood.info> On Sat, Apr 04, 2015 at 02:21:19PM -0500, boB Stepp wrote: > To my mind, would: > > def quit(): > print('Hello lambda world!') > sys.exit() > > and: > > widget = Button(None, text='Hello event world!', command=quit) > > be preferable Python style? Hell yes! Using `or` to run functions purely for their side-effects (in this case, printing and exiting) makes a nice trick, but I wouldn't use for real. On the other hand, using `or` for its value is perfectly acceptable. E.g. one common idiom might be to iterate over something which might be None: for value in maybe_list or []: ... If `maybe_list` is a non-empty list, it is used; if it is an empty list, the second operand (also an empty list) is used, but that's okay since they are both empty lists; and if it is None, then the second operand is used instead. This is a reasonable idiom to use, and prior to Python 2.5 it was the closest thing the language had to a "ternary if operator". These days, the `or` idiom is less common except in old code or code that has to run on Python 2.4 or older. Instead, we might write: for value in (maybe_list if maybe_list is not None else []): ... I'm not entirely sure that's an improvement :-) -- Steve From cs at zip.com.au Sun Apr 5 05:21:23 2015 From: cs at zip.com.au (Cameron Simpson) Date: Sun, 5 Apr 2015 13:21:23 +1000 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: <20150404173408.GJ25453@ando.pearwood.info> References: <20150404173408.GJ25453@ando.pearwood.info> Message-ID: <20150405032123.GA47234@cskk.homeip.net> On 05Apr2015 03:34, Steven D'Aprano wrote: >On Sat, Apr 04, 2015 at 11:49:08AM -0500, boB Stepp wrote: >> widget = Button(None, >> text='Hello event world!', >> command=(lambda: print('Hello lambda world!') or sys.exit())) > >That's either the most horrible misuse of lambda I've ever seen, or a >really cool and rather nifty trick. I'm not sure which :-) I think it is misuse. When I need to run two functions like that I tend to use a tuple: lambda: (f1(), f2()) Since Python evaluates left to right, these functions are called f1 first, then f2. Using "or" introduces a reliance on f1 returning a falsish value. Dodgy and unreliable. Not to mention conflating the supposed Boolean value computed by the expression with the program's purpose. Like others, I agree it is generally better to define a function more normally and just name in instead of inlining a lambda. But sometimes (rarely) that makes for harder to read code structure (though easier to read function internals). Anyway, faced with a desire to use a lambda here, I would choose a tuple. Cheers, Cameron Simpson This is my simple religion. There is no need for temples; no need for complicated philosophy. Our own brain, our own heart is our temple; the philosophy is kindness. - Dalai Lama From steve at pearwood.info Sun Apr 5 05:32:08 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 5 Apr 2015 13:32:08 +1000 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: <20150405033208.GM25453@ando.pearwood.info> On Sun, Apr 05, 2015 at 12:55:16AM +0100, Alan Gauld wrote: > On 04/04/15 22:57, boB Stepp wrote: > >On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld > >wrote: > >>He could have done it in various other ways too: > >> > >>eg. > >>lambda : all(print('Hello lambda world!'), sys.exit() ) > > > >Is this what you meant? Because print will always return False. Or did > >you actually mean: > > > >lambda: any(print('Hello lambda world!'), sys.exit()) > > any() would be more obvious, but in my interpreter > both any() and all() evaluate both functions before > testing the results. At least they do once you > fix the TypeError : they should be in a list/tuple... > > lambda : all([print('Hello lambda world!'), sys.exit()] ) That's because the sys.exit() call leaves the interpreter because any() gets a chance to raise TypeError :-) Your code: lambda: all(print('Hello lambda world!'), sys.exit()) is equivalent to this: a = print('Hello lambda world!') b = sys.exit() # Goodbye cruel world! all(a, b) # this never gets called so you could replace the call to all() with any(), or len(), or zxcvbnm() if you like, it makes no difference at all. The moral equivalent of the original `or` trick would be something like this: any(spam() for spam in [lambda: print("Hello lambda world!"), os.exit]) which now avoids calling os.exit until necessary. E.g. we might write a function which prints a message, then has a 50% chance of exiting: any(spam() for spam in [lambda: print("Hello lambda world!"), lambda: random.random() > 0.5, lambda: print("Goodbye cruel world!"), os.exit] ) will always print Hello, and fifty percent of the time will print Goodbye then exit, otherwise it will return True. -- Steve From steve at pearwood.info Sun Apr 5 06:08:44 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 5 Apr 2015 14:08:44 +1000 Subject: [Tutor] Functional Programming in Python In-Reply-To: <551D6BD4.8030507@gmail.com> References: <551D6BD4.8030507@gmail.com> Message-ID: <20150405040844.GO25453@ando.pearwood.info> On Thu, Apr 02, 2015 at 12:18:28PM -0400, WolfRage wrote: > These are just some questions that I have regarding the topic of > Functional Programming. I am working towards a more functional approach > to programming but acknowledge that it is far from Functional, > especially since this is mostly impossible in Python. You might like to read this: https://codewords.recurse.com/issues/one/an-introduction-to-functional-programming I'm not sure whether I agree with the author, but it's worth reading. -- Steve From robertvstepp at gmail.com Sun Apr 5 05:45:27 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 4 Apr 2015 22:45:27 -0500 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On Sat, Apr 4, 2015 at 6:55 PM, Alan Gauld wrote: > On 04/04/15 22:57, boB Stepp wrote: >> >> On Sat, Apr 4, 2015 at 3:35 PM, Alan Gauld >> wrote: >>> >>> He could have done it in various other ways too: >>> >>> eg. >>> lambda : all(print('Hello lambda world!'), sys.exit() ) >> >> >> Is this what you meant? Because print will always return False. Or did >> you actually mean: >> >> lambda: any(print('Hello lambda world!'), sys.exit()) > > > any() would be more obvious, but in my interpreter > both any() and all() evaluate both functions before > testing the results. At least they do once you > fix the TypeError : they should be in a list/tuple... > > lambda : all([print('Hello lambda world!'), sys.exit()] ) Well, now I am curious as to why the "all" form evaluates BOTH elements. Apparently it does not apply the short-circuit logic we have been discussing, or it would stop evaluating after the print statement return. Why is that? -- boB From cs at zip.com.au Sun Apr 5 06:22:30 2015 From: cs at zip.com.au (Cameron Simpson) Date: Sun, 5 Apr 2015 14:22:30 +1000 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: <20150405042230.GA16357@cskk.homeip.net> On 04Apr2015 22:45, boB Stepp wrote: >On Sat, Apr 4, 2015 at 6:55 PM, Alan Gauld wrote: >> lambda : all([print('Hello lambda world!'), sys.exit()] ) > >Well, now I am curious as to why the "all" form evaluates BOTH >elements. Apparently it does not apply the short-circuit logic we have >been discussing, or it would stop evaluating after the print statement >return. Why is that? Because the list/tuple is constructed entirely before all() is called. All() operates only on the final values. Cheers, Cameron Simpson Yesterday, I was running a CNC plasma cutter that's controlled by Windows XP. This is a machine that moves around a plasma torch that cuts thick steel plate. ?A "New Java update is available" window popped up while I was working. ?Not good. - John Nagle From davea at davea.name Sun Apr 5 07:16:32 2015 From: davea at davea.name (Dave Angel) Date: Sun, 05 Apr 2015 01:16:32 -0400 Subject: [Tutor] Functional Programming in Python In-Reply-To: <55209598.7010801@gmail.com> References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> <551D9A31.3040509@gmail.com> <20150403032331.GB25453@ando.pearwood.info> <55209598.7010801@gmail.com> Message-ID: <5520C530.1010902@davea.name> On 04/04/2015 09:53 PM, WolfRage wrote: > > > (Pointing to the different classes. Since C++ has virtual methods but > Python does not?) I'd say that all methods in Python are virtual, except for those which are classmethod or staticmethod. -- DaveA From steve at pearwood.info Sun Apr 5 07:23:47 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 5 Apr 2015 15:23:47 +1000 Subject: [Tutor] Functional Programming in Python In-Reply-To: <55209598.7010801@gmail.com> References: <551D6BD4.8030507@gmail.com> <20150402180712.GY25453@ando.pearwood.info> <551D9A31.3040509@gmail.com> <20150403032331.GB25453@ando.pearwood.info> <55209598.7010801@gmail.com> Message-ID: <20150405052346.GP25453@ando.pearwood.info> On Sat, Apr 04, 2015 at 09:53:28PM -0400, WolfRage wrote: > > So I was surprised I did not get more feedback on my abused coroutine, > maybe that is good or bad, not sure. Perhaps people didn't understand it. Or see it :-) > Any ways I am on to trying to make that coroutine act more like the > State Pattern from Gang of Four. And well reading this: > http://gameprogrammingpatterns.com/state.html Now you're fighting the paradigm. Functional programming works best for code that avoids side-effects. But changes of state are naturally a side-effect! I was sitting, now I am walking. It's still me, but my state is different. Now of course you can emulate state changes using purely functional code, but its harder and less efficient. > I am not sure how to do this: > class Heroine > { > public: > virtual void handleInput(Input input) > { > state_->handleInput(*this, input); > } > > virtual void update() > { > state_->update(*this); > } > > // Other methods... > private: > HeroineState* state_; > }; > > (Pointing to the different classes. Since C++ has virtual methods but > Python does not?) in Python? Do I just reference the new method? Because > state_ will always be the correct object? Hmmm, I'm not sure, but I think that we would say that *all* Python methods are virtual in C++ terms. They are all resolved at runtime. There are a few ways we might do this in Python. class Heroine: def __init__(self): self.state = "standing" # Or use an Enum in Python 3.4 def jump(self): if self.state == "standing": self.state = "jumping" ... elif self.state == "jumping": pass # Dispatch table of keys to actions. KEYMAP = {'b': jump, 'd': duck, 'f': run, ... } def handle_keypress(self, key): method = self.KEYMAP.get(key, None) if method: method(self) We look up the key press, and get a reference to the method itself, not the name of the method. (Or None.) We then call that method by providing self as the first argument. Nice and easy. It's so easy that I'm not sure if it's even worth discussing alternatives. Another alternative might be to use delegation, or object composition. Give the Heroine class all the methods which don't change. For the methods which do change, create a separate FooState class for each state: class JumpingState: def jump(self): pass def duck(self): ... class RunningState: ... class Heroine: def __init__(self): self.state = StandingState() # Dispatch table of keys to method names. KEYMAP = {'b': 'jump', 'd': 'duck', 'f': 'run', ... } def handle_keypress(self, key): name = self.KEYMAP.get(key, None) if name: newstate = getattr(self.state, name)() if newstate: self.state = newstate() Methods of the state object can signal a change of state by returning the class representing the new state. Otherwise, they can return None to signal no change of state. Here is how we might do this using inheritence instead of composition. Start with a base class and a bunch of default methods which conditionally raise: class BaseHeroine: def jump(self): if self.__class__ is BaseHeroine: raise RuntimeError def run(self): if self.__class__ is BaseHeroine: raise RuntimeError def duck(self): if self.__class__ is BaseHeroine: raise RuntimeError # Dispatch table of keys to method names. KEYMAP = {'b': 'jump', 'd': 'duck', 'f': 'run', ... } def handle_keypress(self, key): name = self.KEYMAP.get(key, None) if name: getattr(self.state, name)() Now have a bunch of subclasses, one for each state. Override only the methods you need. (Remember, the default behaviour for each method is to do nothing, if called from a subclass. They only raise if called from the base class.) class JumpHeroine(BaseHeroine): ... class StandHeroine(BaseHeroine): ... class RunHeroine(BaseHeroine): ... Now create an instance, and set its state: heroine = BaseHeroine() heroine.__class__ = StandHeroine State transitions are managed by *changing the instance's class*. Methods can do that themselves: def spam(self): self.__class__ = RunHeroine # Don't instantiate the class. print("Spam spam spam loverlllly spam!!!!") Now, I haven't tested any of the above code, but here is a short and simple demonstration showing that it does work: py> class X: ... def display(self): ... print("in X") ... def method(self): ... self.display() ... print(self, type(self), self.__class__) ... py> class Y(X): ... def display(self): ... print("in Y") ... py> instance = X() py> instance.method() in X <__main__.X object at 0xb7a9d84c> py> instance.__class__ = Y # dynamically change the class py> instance.method() in Y <__main__.Y object at 0xb7a9d84c> Cool, huh? :-) Having written all this out, I'm now starting to lean towards the inheritence version. Now, how you would this in a purely functional style... I have no idea! -- Steve From alan.gauld at btinternet.com Sun Apr 5 10:06:21 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 05 Apr 2015 09:06:21 +0100 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On 05/04/15 04:45, boB Stepp wrote: >>>> He could have done it in various other ways too: >>>> >>>> eg. >>>> lambda : all(print('Hello lambda world!'), sys.exit() ) > Well, now I am curious as to why the "all" form evaluates BOTH > elements. Apparently it does not apply the short-circuit logic we have > been discussing, or it would stop evaluating after the print statement > return. Why is that? Because I didn't really think the example through properly. I just grabbed the first thing I could think of that would evaluate both functions... As Cameron has shown, a much more elegant solution is just to use a tuple as the body of the lambda. That's effectively what's happening indside the all()/any() calls. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From marcus.luetolf at bluewin.ch Sun Apr 5 13:11:06 2015 From: marcus.luetolf at bluewin.ch (=?iso-8859-1?Q?Marcus_L=FCtolf?=) Date: Sun, 5 Apr 2015 13:11:06 +0200 Subject: [Tutor] Loops Message-ID: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> Why do I get this traceback with the infinite loop below but not with the definitw loop (bottom of mail)? Thanks for help, Marcus. count = 0 total = 0 while True: x = raw_input('Enter a number') count = count + 1 total = total + x print count, total, (total/count) Traceback (most recent call last): File "C:\Python27\enter_a_number.py", line 6, in total = total + x TypeError: unsupported operand type(s) for +: 'int' and 'str' --- Diese E-Mail wurde von Avast Antivirus-Software auf Viren gepr?ft. http://www.avast.com From breamoreboy at yahoo.co.uk Sun Apr 5 15:11:36 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Sun, 05 Apr 2015 14:11:36 +0100 Subject: [Tutor] Loops In-Reply-To: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> References: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> Message-ID: On 05/04/2015 12:11, Marcus L?tolf wrote: > Why do I get this traceback with the infinite loop below but not with the > definitw loop (bottom of mail)? > Thanks for help, Marcus. > > count = 0 > total = 0 > while True: > > x = raw_input('Enter a number') > count = count + 1 > total = total + x > print count, total, (total/count) > > Traceback (most recent call last): > > File "C:\Python27\enter_a_number.py", line 6, in > > total = total + x > > TypeError: unsupported operand type(s) for +: 'int' and 'str' > raw_input returns a string, you must convert that to an int (or some other numeric type) before you can add it to your total. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From alan.gauld at btinternet.com Sun Apr 5 15:18:36 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 05 Apr 2015 14:18:36 +0100 Subject: [Tutor] Loops In-Reply-To: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> References: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> Message-ID: On 05/04/15 12:11, Marcus L?tolf wrote: > Why do I get this traceback with the infinite loop below but not with the > definitw loop (bottom of mail)? I don;t see anyt loops at the bottom. But as for this one... > count = 0 > total = 0 > > while True: > x = raw_input('Enter a number') raw_input reads a character string. You need to converrt it to a number: x = int(raw_input('Enter a number') ) > count = count + 1 > total = total + x Without the conversion you are trying to add a string to a number which is illegal in Python. > print count, total, (total/count) > Traceback (most recent call last): > File "C:\Python27\enter_a_number.py", line 6, in > total = total + x > TypeError: unsupported operand type(s) for +: 'int' and 'str' Which is what the error is telling you. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Sun Apr 5 16:54:33 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 6 Apr 2015 00:54:33 +1000 Subject: [Tutor] Loops In-Reply-To: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> References: <40c601d06f91$398b5cc0$aca21640$@bluewin.ch> Message-ID: <20150405145432.GR25453@ando.pearwood.info> On Sun, Apr 05, 2015 at 01:11:06PM +0200, Marcus L?tolf wrote: > Why do I get this traceback with the infinite loop below but not with the > definitw loop (bottom of mail)? You forgot to show the definite loop, but the error in the infinite loop is explained by the error message. You should read the error message carefully, it will often explain the problem you are having. Further comments below. > count = 0 > total = 0 > while True: > x = raw_input('Enter a number') > count = count + 1 > total = total + x > print count, total, (total/count) > > > Traceback (most recent call last): > File "C:\Python27\enter_a_number.py", line 6, in > total = total + x > TypeError: unsupported operand type(s) for +: 'int' and 'str' The traceback shows you the line causing the error: total = total + x and describes the error: you cannot add an int and a str. Try it at the interactive interpreter: py> 23 + "42" Traceback (most recent call last): File "", line 1, in TypeError: unsupported operand type(s) for +: 'int' and 'str' The `total` variable starts as an int: total = 0 and x is a string. Just because you print "Enter a number" doesn't mean that Python magically turns x into a number. You are responsible for turning the string into a number. Try: x = int(raw_input('Enter a number')) -- Steve From robertvstepp at gmail.com Sun Apr 5 21:29:32 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 5 Apr 2015 14:29:32 -0500 Subject: [Tutor] Use of "or" in a lambda expression In-Reply-To: References: Message-ID: On Sun, Apr 5, 2015 at 3:06 AM, Alan Gauld wrote: > On 05/04/15 04:45, boB Stepp wrote: > >>>>> He could have done it in various other ways too: >>>>> >>>>> eg. >>>>> lambda : all(print('Hello lambda world!'), sys.exit() ) > > >> Well, now I am curious as to why the "all" form evaluates BOTH >> elements. Apparently it does not apply the short-circuit logic we have >> been discussing, or it would stop evaluating after the print statement >> return. Why is that? > > > Because I didn't really think the example through properly. > I just grabbed the first thing I could think of that would > evaluate both functions... As Cameron has shown, a much more > elegant solution is just to use a tuple as the body of > the lambda. Not to worry, Alan! This gave me an opportunity to read up on and learn more about all() and any(), which I had not encountered previously. Also, much has been clarified about the details of how and when things get evaluated for various approaches to these lambda expressions. Many thanks! -- boB From narci.venturini at gmail.com Sun Apr 5 16:12:32 2015 From: narci.venturini at gmail.com (Narci Edson Venturini) Date: Sun, 5 Apr 2015 11:12:32 -0300 Subject: [Tutor] Matrix bug Message-ID: The next code has an unexpected result: >>>a=3*[3*[0]] >>>a [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>>a[0][0]=1 >>>a [[1, 0, 0], [1, 0, 0], [1, 0, 0]] The code assigned to "1" a(0,0), a(1,0) and a(2,0). It was expected: [[1, 0, 0], [0, 0, 0], [0, 0, 0]] When the followind code is ran, them the correct result is obtained: >>>a=[[0 for i in range(3)] for j in range(3)] >>>>>>a [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>>a[0][0]=1 >>>a [[1, 0, 0], [0, 0, 0], [0, 0, 0]] So, what is wrong ? Best Regars, Narci __________________ Narci Edson Venturini (19) 99733-8420 From solomon.vimal at gmail.com Sun Apr 5 15:39:02 2015 From: solomon.vimal at gmail.com (Solomon Vimal) Date: Sun, 5 Apr 2015 09:39:02 -0400 Subject: [Tutor] Python dir(handle) function acts weird Message-ID: Hi, I have two versions of the same software S4.1 and S5, say - they are treated as COM handles. When I use methodsview in MATLAB to see the list of methods in both, I get more or less the same function list, but in Python, when I use dir(s4.1) I get the identical list to MATLAB methodsview, but dir(s5) is a subset of the list. This is weird behavior I thought. Does anyone know what is wrong here? Please let me know soon. Thanks a lot! Solomon. Solomon Vimal (+1)9198690115 From alan.gauld at btinternet.com Sun Apr 5 23:36:13 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 05 Apr 2015 22:36:13 +0100 Subject: [Tutor] Python dir(handle) function acts weird In-Reply-To: References: Message-ID: On 05/04/15 14:39, Solomon Vimal wrote: > Hi, > I have two versions of the same software S4.1 and S5, say - they are > treated as COM handles. > When I use methodsview in MATLAB to see the list of methods in both, I get > more or less the same function list, but in Python, when I use dir(s4.1) I > get the identical list to MATLAB methodsview, but dir(s5) is a subset of > the list. This is weird behavior I thought. > > Does anyone know what is wrong here? Please let me know soon. Sorry I can't help, but its not really a Python question so much as a Windows interface issue. You don't say how you are accessing the COM objects but ctypes and PyWin32 are both addressed by the Python windows mailing list. I suggest you might get a more comprehensive reply there. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From emile at fenx.com Sun Apr 5 23:43:15 2015 From: emile at fenx.com (Emile van Sebille) Date: Sun, 05 Apr 2015 14:43:15 -0700 Subject: [Tutor] Matrix bug In-Reply-To: References: Message-ID: On 4/5/2015 7:12 AM, Narci Edson Venturini wrote: > The next code has an unexpected result: > >>>> a=3*[3*[0]] a now contains three references to the same object, hence the results you show below. You can create three distinct objects as follows: >>> a = [ [0,0,0] for i in (0,1,2) ] >>> a[1][1]=1 >>> a [[0, 0, 0], [0, 1, 0], [0, 0, 0]] >>> hth, Emile >>>> a > [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>>> a[0][0]=1 >>>> a > [[1, 0, 0], [1, 0, 0], [1, 0, 0]] > > The code assigned to "1" a(0,0), a(1,0) and a(2,0). > > It was expected: [[1, 0, 0], [0, 0, 0], [0, 0, 0]] > > When the followind code is ran, them the correct result is obtained: > >>>> a=[[0 for i in range(3)] for j in range(3)] >>>>>>> a > [[0, 0, 0], [0, 0, 0], [0, 0, 0]] >>>> a[0][0]=1 >>>> a > [[1, 0, 0], [0, 0, 0], [0, 0, 0]] > > So, what is wrong ? > > Best Regars, > > > > Narci > __________________ > Narci Edson Venturini > (19) 99733-8420 > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From alan.gauld at btinternet.com Sun Apr 5 23:46:51 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 05 Apr 2015 22:46:51 +0100 Subject: [Tutor] Matrix bug In-Reply-To: References: Message-ID: On 05/04/15 15:12, Narci Edson Venturini wrote: > The next code has an unexpected result: > >>>> a=3*[3*[0]] Note that this makes three references to the list of 3 references to 0. In other words you reference the same list 3 times. So when you change the first copy you change the other 2 also. Put another way: >>> mylist = [0,0,0] >>> a = 3 * [mylist] 'a' now contains 3 references to mylist, making 4 references altogether to the same list object. If I change the list via any of them it will change in all the places it is referenced: >>> mylist[0] = 1 # replace a zero with a one >>> mylist [1, 0, 0] >>> a [[1, 0, 0], [1, 0, 0], [1, 0, 0]] > When the followind code is ran, them the correct result is obtained: > >>>> a=[[0 for i in range(3)] for j in range(3)] This created 3 new lists. In fact you could simplify it to: a = [[0,0,0] for i in range(3)] HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Mon Apr 6 02:38:16 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 6 Apr 2015 10:38:16 +1000 Subject: [Tutor] Matrix bug In-Reply-To: References: Message-ID: <20150406003815.GT25453@ando.pearwood.info> On Sun, Apr 05, 2015 at 11:12:32AM -0300, Narci Edson Venturini wrote: > The next code has an unexpected result: > > >>>a=3*[3*[0]] > >>>a > [[0, 0, 0], [0, 0, 0], [0, 0, 0]] > >>>a[0][0]=1 > >>>a > [[1, 0, 0], [1, 0, 0], [1, 0, 0]] It isn't obvious, and it is *very* common for people to run into this and be confused, but that is actually working by design. The * operator for lists does not copy the list items, it makes multiple references to it. Let's have a look at an example. We start with an arbitrary object: py> class X: pass ... py> x = X() py> print(x) <__main__.X object at 0xb7a9d92c> Printing the object x shows us the memory location of x: 0xb7a9d92c. Now let us put it in a list, and replicate it: py> mylist = [x]*3 py> print(mylist) [<__main__.X object at 0xb7a9d92c>, <__main__.X object at 0xb7a9d92c>, <__main__.X object at 0xb7a9d92c>] Do you see how *all three* list items have the same memory location? Rather than get three different X objects, we have the same object, repeated three times. So these two lines are essentially identical: mylist = [x]*3 mylist = [x, x, x] Now, in practice, sometimes that makes a difference, and sometimes it doesn't. If you use an int or a str, it makes no difference: py> mylist = [1]*5 py> mylist [1, 1, 1, 1, 1] Let's look at their ID numbers and see that they are identical: py> for item in mylist: ... print(id(item)) ... 136560640 136560640 136560640 136560640 136560640 So it is the same int object repeated five times, not five different objects. But that doesn't matter, since there is no way to change the value of the object: ints are immutable, and 1 is always 1. You can only *replace* the object with a new object: py> mylist[0] = 2 py> print(mylist) [2, 1, 1, 1, 1] Now let's do it again with a list of lists: py> mylist = [[]]*5 py> mylist [[], [], [], [], []] py> for item in mylist: ... print(id(item)) ... 3081330988 3081330988 3081330988 3081330988 3081330988 So you can see, we now have the same list repeated five times, not five different lists. If we *replace* one of the items, using = assignment, everything behaves as expected: py> mylist[0] = [1,2,3] # Replace the first item. py> print(mylist) [[1, 2, 3], [], [], [], []] But if we modify one of the items, you may be surprised: py> mylist[1].append(999) # Change the second item in place. py> print(mylist) [[1, 2, 3], [999], [999], [999], [999]] The solution to this "gotcha" is to avoid list multiplication except for immutable objects like ints and strings. So to get a 3 x 3 array of all zeroes, I would write: py> array = [[0]*3 for i in range(3)] py> print(array) [[0, 0, 0], [0, 0, 0], [0, 0, 0]] py> array[0][1] += 1 py> print(array) [[0, 1, 0], [0, 0, 0], [0, 0, 0]] -- Steve From steve at pearwood.info Mon Apr 6 02:43:58 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 6 Apr 2015 10:43:58 +1000 Subject: [Tutor] Python dir(handle) function acts weird In-Reply-To: References: Message-ID: <20150406004358.GU25453@ando.pearwood.info> On Sun, Apr 05, 2015 at 09:39:02AM -0400, Solomon Vimal wrote: > Hi, > I have two versions of the same software S4.1 and S5, say - they are > treated as COM handles. > When I use methodsview in MATLAB to see the list of methods in both, I get > more or less the same function list, but in Python, when I use dir(s4.1) I > get the identical list to MATLAB methodsview, but dir(s5) is a subset of > the list. This is weird behavior I thought. > > Does anyone know what is wrong here? Please let me know soon. I have no idea what you are talking about. What are S4.1 and S5? What sort of software are they? What is methodsview in MATLAB? How are you using the same software in MATLAB and Python? You cannot run dir(s4.1) in Python, that's a syntax error. So what are you actually doing? Please COPY and PASTE the exact code you are using, don't summarise it, and especially don't write it out from memory. Remember that we cannot see your computer, nor do we understand the background to your question. Don't assume we are MATLAB experts. -- Steve From robertvstepp at gmail.com Mon Apr 6 16:54:47 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Mon, 6 Apr 2015 09:54:47 -0500 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? Message-ID: Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit (Intel)] on win32 Type "copyright", "credits" or "license()" for more information. >>> d = {'n': 'Print me!'} >>> d {'n': 'Print me!'} >>> d['n'] 'Print me!' >>> def func(d['n']): SyntaxError: invalid syntax >>> def func(d): print d['n'] >>> func(d) Print me! The plain text does not show it, but in the invalid syntax the "[" is highlighted red. Why is it invalid syntax to pass a particular dictionary value in a function? Or does it require a different form to do so? Thanks! -- boB From joel.goldstick at gmail.com Mon Apr 6 17:20:24 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Mon, 6 Apr 2015 11:20:24 -0400 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: On Mon, Apr 6, 2015 at 10:54 AM, boB Stepp wrote: > Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit > (Intel)] on win32 > Type "copyright", "credits" or "license()" for more information. >>>> d = {'n': 'Print me!'} >>>> d > {'n': 'Print me!'} >>>> d['n'] > 'Print me!' >>>> def func(d['n']): > SyntaxError: invalid syntax >>>> def func(d): > print d['n'] > >>>> func(d) > Print me! > > The plain text does not show it, but in the invalid syntax the "[" is > highlighted red. > > Why is it invalid syntax to pass a particular dictionary value in a > function? Or does it require a different form to do so? > Here is another example: >>> def f(6): File "", line 1 def f(6): ^ SyntaxError: invalid syntax >>> You can't pass a value as a parameter to a function definition. You need to provide a name. The actual value is supplied when you call the function > Thanks! > > -- > boB > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From joel.goldstick at gmail.com Mon Apr 6 17:38:37 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Mon, 6 Apr 2015 11:38:37 -0400 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: On Mon, Apr 6, 2015 at 11:20 AM, Joel Goldstick wrote: > On Mon, Apr 6, 2015 at 10:54 AM, boB Stepp wrote: >> Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit >> (Intel)] on win32 >> Type "copyright", "credits" or "license()" for more information. >>>>> d = {'n': 'Print me!'} >>>>> d >> {'n': 'Print me!'} >>>>> d['n'] >> 'Print me!' >>>>> def func(d['n']): >> SyntaxError: invalid syntax >>>>> def func(d): >> print d['n'] >> >>>>> func(d) >> Print me! >> >> The plain text does not show it, but in the invalid syntax the "[" is >> highlighted red. >> >> Why is it invalid syntax to pass a particular dictionary value in a >> function? Or does it require a different form to do so? >> > > Here is another example: > >>>> def f(6): > File "", line 1 > def f(6): > ^ > SyntaxError: invalid syntax >>>> > > You can't pass a value as a parameter to a function definition. You > need to provide a name. The actual value is supplied when you call > the function The python.org site has this: https://docs.python.org/2/reference/compound_stmts.html#function-definitions > >> Thanks! >> >> -- >> boB >> _______________________________________________ >> Tutor maillist - Tutor at python.org >> To unsubscribe or change subscription options: >> https://mail.python.org/mailman/listinfo/tutor > > > > -- > Joel Goldstick > http://joelgoldstick.com -- Joel Goldstick http://joelgoldstick.com From davea at davea.name Mon Apr 6 18:31:16 2015 From: davea at davea.name (Dave Angel) Date: Mon, 06 Apr 2015 12:31:16 -0400 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: <5522B4D4.7060500@davea.name> On 04/06/2015 10:54 AM, boB Stepp wrote: > Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit > (Intel)] on win32 > Type "copyright", "credits" or "license()" for more information. >>>> d = {'n': 'Print me!'} >>>> d > {'n': 'Print me!'} >>>> d['n'] > 'Print me!' >>>> def func(d['n']): > SyntaxError: invalid syntax >>>> def func(d): > print d['n'] > >>>> func(d) > Print me! > > The plain text does not show it, but in the invalid syntax the "[" is > highlighted red. > > Why is it invalid syntax to pass a particular dictionary value in a > function? Or does it require a different form to do so? You're getting confused between defining a function and calling one. For Python 2.7, see: https://docs.python.org/2/reference/compound_stmts.html#function-definitions When defining a function, you provide (not pass) the formal parameters, and they must be simple names. Those names will end up being local variables when the function is finally called. (The only sort-of exception to this in 2.7 is when you define a default argument to a function. In that case, the parameter still must be a valid python variable name, but the default value can be an arbitrary expression, as long as it's valid at the time of function definition.) Once the function is being called, then you can use an arbitrary expression for your argument. The results of that expression is bound to the formal parameter specified above. Further reading: https://docs.python.org/2/faq/programming.html#faq-argument-vs-parameter https://docs.python.org/2/glossary.html#term-parameter https://docs.python.org/2/glossary.html#term-argument Now, it's possible that what you're trying to do is something that can be accomplished some other way. So please elaborate on your purpose in using the syntax you did. Or supply a small program that shows a function being defined and called, that would give meaning to the syntax you're trying. -- DaveA From robertvstepp at gmail.com Mon Apr 6 18:43:11 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Mon, 6 Apr 2015 11:43:11 -0500 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: <5522B4D4.7060500@davea.name> References: <5522B4D4.7060500@davea.name> Message-ID: Thanks, Joel! Thanks, Dave! On Mon, Apr 6, 2015 at 11:31 AM, Dave Angel wrote: [...] > Now, it's possible that what you're trying to do is something that can be > accomplished some other way. So please elaborate on your purpose in using > the syntax you did. Or supply a small program that shows a function being > defined and called, that would give meaning to the syntax you're trying. I was breaking down longer functions into smaller ones. Along the way I noticed I was passing an entire dictionary from one function to another. I only needed to pass one particular value, not the whole dictionary, so that is how I got into the issue I asked about. Once you and Joel responded it was *obvious*. A bunch of years ago, it would have been *obvious* and I never would have asked the question in the first place. This is easy enough to correct now that I realize what I was doing. -- boB From davea at davea.name Mon Apr 6 19:54:58 2015 From: davea at davea.name (Dave Angel) Date: Mon, 06 Apr 2015 13:54:58 -0400 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: <5522B4D4.7060500@davea.name> Message-ID: <5522C872.7000003@davea.name> On 04/06/2015 12:43 PM, boB Stepp wrote: > > I was breaking down longer functions into smaller ones. Along the way > I noticed I was passing an entire dictionary from one function to > another. I only needed to pass one particular value, not the whole > dictionary, so that is how I got into the issue I asked about. Just to reinforce something you probably know well, passing a dictionary takes no more memory or time than passing an item from that dictionary. The real choice is whether the called function should dealing with a single item or with a dictionary. It would have a different name in each case, and a different set of reuse possibilities. I know the following example abuses the dictionary, using it as though it were an instance of class Person. It's just what popped into my head. def check_person(person): if person["name"] in list_of_preferred: do_something... return True return False def check_name(name): if name in list_of_preferred: do_something... return True return False In the first case, the function would be able use other elements of the dictionary, like "email_address" or "phone_number". In the second case, you could call the function from someplace that has only names, and isn't worried about what dict the name might be part of. -- DaveA From anubhav1691 at gmail.com Mon Apr 6 12:46:29 2015 From: anubhav1691 at gmail.com (Anubhav Yadav) Date: Mon, 6 Apr 2015 16:16:29 +0530 Subject: [Tutor] Need some help with setuptools for my project. Message-ID: Hi, I am new to python and still trying to get my concepts clear with respect to standard practices in python. I wrote a script which fetches the latest cricket scores from the internet and sends desktop notifications using pynotify. The project, initially supported both python2 as well as python3, but I realized it is very difficult to keep up with the errors. So I migrated the project to python2. Now I wanted to make my script robust such that it could be installed easily by the users. I broke up my script in logical modules and added them all under root directory with the name of the project. Here is how the source tree looks now: |-- LICENSE |-- README.md |-- requirements.txt |-- scorer | |-- app.py | |-- fetch_scores.py | |-- __init__.py | |-- __main__.py | |-- notification.py | |-- system.py | `-- ui.py `-- setup.py Where scorer is the name of the project. Here are the contents of the requirements.txt file: scorer requests==2.6.0 beautifulsoup4==4.3.2 And here is my setup.py from setuptools import setup def readme(): with open('README.md') as f: return f.read() setup( name = 'scorer', version = 0.1, description = 'A simple script to show desktop notifications for cricket scores', long_description = readme(), url = 'https://github.com/neo1691/scorer.py', author = 'Anubhav Yadav', author_email = 'anubhav1691 at gmail.com', license = 'GPLv2', packages = ['scorer'], install_requires=[ 'requests', 'beautifulsoup4', ], zip_safe = False ) When I run ``python setup.py build``, It gives me the following output: running build running build_py creating build creating build/lib.linux-x86_64-2.7 creating build/lib.linux-x86_64-2.7/scorer copying scorer/ui.py -> build/lib.linux-x86_64-2.7/scorer copying scorer/__init__.py -> build/lib.linux-x86_64-2.7/scorer copying scorer/system.py -> build/lib.linux-x86_64-2.7/scorer copying scorer/fetch_scores.py -> build/lib.linux-x86_64-2.7/scorer copying scorer/__main__.py -> build/lib.linux-x86_64-2.7/scorer copying scorer/app.py -> build/lib.linux-x86_64-2.7/scorer copying scorer/notification.py -> build/lib.linux-x86_64-2.7/scorer It creates a build directory with the above files, and I have no idea what to do with them. How to use it? Or how to test my app without installing it. If I then run ``sudo python setup.py install``, it gives me a lot of output but one of the lines is: Installed /usr/lib/python2.7/site-packages/scorer-0.1-py2.7.egg A few more directories are created in my project directory, build, dist, scorer.egg-info etc. Yet I still have no idea how to run my app. I can run my app from the root of the project directory using ``python -m scorer`` since I have called my main() function using the __main__.py file. Can someone help me figure out how can I package my project according to setuptools format? Also can someone tell me how to un-install the project from systemwide after running ``sudo python setup.py install``? Any help would be greatly appreciated. I apologize if my question does not belongs to this mailing list. My project is hosted on github[1]. Thank you. [1] https://github.com/neo1691/scorer.py -- Regards, Anubhav Yadav KPIT Technologies, Pune. From cybervigilante at gmail.com Mon Apr 6 16:05:27 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Mon, 6 Apr 2015 07:05:27 -0700 Subject: [Tutor] failed filter result Message-ID: Why did this fail where it did? It failed at listing the result of the filter of a word list, but I figured if it failed, it would have done so at the filter. >>> words = open('5desk.txt').readlines() >>> k = [word.rstrip for word in words] >>> len(k) 61406 >>> p = filter(lambda word: len(word) > 10, k) >>> p >>> list(p) Traceback (most recent call last): File "", line 301, in runcode File "", line 1, in File "", line 1, in TypeError: object of type 'builtin_function_or_method' has no len() -- Jim I can't think of a clever tagline today, so just imagine I said something clever. From timomlists at gmail.com Mon Apr 6 20:06:39 2015 From: timomlists at gmail.com (Timo) Date: Mon, 06 Apr 2015 20:06:39 +0200 Subject: [Tutor] failed filter result In-Reply-To: References: Message-ID: <5522CB2F.3070402@gmail.com> Op 06-04-15 om 16:05 schreef Jim Mooney: > Why did this fail where it did? It failed at listing the result of the > filter of a word list, but I figured if it failed, it would have done so at > the filter. > >>>> words = open('5desk.txt').readlines() >>>> k = [word.rstrip for word in words] Your problem is in the above line. Have this example: >>> words = ["foo", "bar", "spam", "eggs"] >>> k = [word.rstrip for word in words] >>> k [, , , ] Looks very similar to your TypeError later on! Let's see what's wrong: >>> "foo".rstrip Still the same... Let's go further: >>> "foo".rstrip() 'foo' Looks much better! So the problem is you're storing the rstrip function instead of calling it and store the result. A big difference. The fix is very easy, just call rstrip in your list comprehension: k = [word.rstrip() for word in words] A little tip: errors like these are easy to debug by printing your values. If you printed k before continuing it wouldn't have happened. Timo >>>> len(k) > 61406 >>>> p = filter(lambda word: len(word) > 10, k) >>>> p > >>>> list(p) > Traceback (most recent call last): > File "", line 301, in runcode > File "", line 1, in > File "", line 1, in > TypeError: object of type 'builtin_function_or_method' has no len() > From alan.gauld at btinternet.com Mon Apr 6 20:12:58 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 06 Apr 2015 19:12:58 +0100 Subject: [Tutor] failed filter result In-Reply-To: References: Message-ID: On 06/04/15 15:05, Jim Mooney wrote: > Why did this fail where it did? It failed at listing the result of the > filter of a word list, but I figured if it failed, it would have done so at > the filter. > >>>> words = open('5desk.txt').readlines() >>>> k = [word.rstrip for word in words] Notice that you are not calling rstrip here. You are creating a list with as many references to word.rstrip as there are words. This is almost certainly not what you want. You need to add the parens. >>>> p = filter(lambda word: len(word) > 10, k) >>>> list(p) > Traceback (most recent call last): > File "", line 301, in runcode > File "", line 1, in > File "", line 1, in > TypeError: object of type 'builtin_function_or_method' has no len() This is because you are passing a list of function references rather than stripped words. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Mon Apr 6 20:16:27 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 06 Apr 2015 19:16:27 +0100 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: On 06/04/15 11:46, Anubhav Yadav wrote: > Any help would be greatly appreciated. I apologize if my question does not > belongs to this mailing list. My project is hosted on github[1]. Using the setup tools and creating/installing projects seems close enough to standard library functions that its on topic so far as I'm concerned :-) Sorry I don't really know the answers to your questions though! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From emile at fenx.com Mon Apr 6 21:20:37 2015 From: emile at fenx.com (Emile van Sebille) Date: Mon, 06 Apr 2015 12:20:37 -0700 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: On 4/6/2015 7:54 AM, boB Stepp wrote: > Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit > (Intel)] on win32 > Type "copyright", "credits" or "license()" for more information. >>>> d = {'n': 'Print me!'} >>>> d > {'n': 'Print me!'} >>>> d['n'] > 'Print me!' >>>> def func(d['n']): > SyntaxError: invalid syntax >>>> def func(d): > print d['n'] > >>>> func(d) > Print me! > > The plain text does not show it, but in the invalid syntax the "[" is > highlighted red. > > Why is it invalid syntax to pass a particular dictionary value in a > function? Or does it require a different form to do so? Maybe this form helps: Python 2.7.6 (default, Mar 22 2014, 22:59:56) [GCC 4.8.2] on linux2 Type "help", "copyright", "credits" or "license" for more information. >>> d = {'a':'123'} >>> def func(s=d['a']): ... print s ... >>> func() 123 Emile From davea at davea.name Mon Apr 6 21:42:40 2015 From: davea at davea.name (Dave Angel) Date: Mon, 06 Apr 2015 15:42:40 -0400 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: <5522E1B0.9070904@davea.name> On 04/06/2015 03:20 PM, Emile van Sebille wrote: > On 4/6/2015 7:54 AM, boB Stepp wrote: >> Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit >> (Intel)] on win32 >> Type "copyright", "credits" or "license()" for more information. >>>>> d = {'n': 'Print me!'} >>>>> d >> {'n': 'Print me!'} >>>>> d['n'] >> 'Print me!' >>>>> def func(d['n']): >> SyntaxError: invalid syntax >>>>> def func(d): >> print d['n'] >> >>>>> func(d) >> Print me! >> >> The plain text does not show it, but in the invalid syntax the "[" is >> highlighted red. >> >> Why is it invalid syntax to pass a particular dictionary value in a >> function? Or does it require a different form to do so? > > Maybe this form helps: > > Python 2.7.6 (default, Mar 22 2014, 22:59:56) > [GCC 4.8.2] on linux2 > Type "help", "copyright", "credits" or "license" for more information. > >>> d = {'a':'123'} > >>> def func(s=d['a']): > ... print s > ... > >>> func() > 123 > Only if you know that nobody is going to be changing d. >>> d = {"a":"123"} >>> def func(s=d["a"]): ... print s ... >>> d["a"] = "new value" >>> func() 123 >>> -- DaveA From breamoreboy at yahoo.co.uk Mon Apr 6 22:08:13 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Mon, 06 Apr 2015 21:08:13 +0100 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: On 06/04/2015 20:20, Emile van Sebille wrote: > On 4/6/2015 7:54 AM, boB Stepp wrote: >> Python 2.7.8 (default, Jun 30 2014, 16:03:49) [MSC v.1500 32 bit >> (Intel)] on win32 >> Type "copyright", "credits" or "license()" for more information. >>>>> d = {'n': 'Print me!'} >>>>> d >> {'n': 'Print me!'} >>>>> d['n'] >> 'Print me!' >>>>> def func(d['n']): >> SyntaxError: invalid syntax >>>>> def func(d): >> print d['n'] >> >>>>> func(d) >> Print me! >> >> The plain text does not show it, but in the invalid syntax the "[" is >> highlighted red. >> >> Why is it invalid syntax to pass a particular dictionary value in a >> function? Or does it require a different form to do so? > > Maybe this form helps: > > Python 2.7.6 (default, Mar 22 2014, 22:59:56) > [GCC 4.8.2] on linux2 > Type "help", "copyright", "credits" or "license" for more information. > >>> d = {'a':'123'} > >>> def func(s=d['a']): > ... print s > ... > >>> func() > 123 > > Emile > Dreadful advice. There have always have been and always will be questions from newbies as they do not understand how this construct works in Python. Please *DO NOT* put such things forward. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From dylanlee.evans95 at gmail.com Mon Apr 6 22:22:59 2015 From: dylanlee.evans95 at gmail.com (Dylan Evans) Date: Mon, 6 Apr 2015 21:22:59 +0100 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: On 6 April 2015 at 18:56:57, tutor-request at python.org (tutor-request at python.org) wrote: > Any help would be greatly appreciated. I apologize if my question does not > belongs to this mailing list. My project is hosted on github[1]. > > Thank you. > > [1] https://github.com/neo1691/scorer.py You might consider packaging your project as a script so that it can be run by the user from the command line. See:?https://docs.python.org/2/distutils/setupscript.html#installing-scripts Provided that you add something like #!/usr/bin/python to the top of scorer.py, 'python setup.py install? will make it executable and move it to /usr/local/bin (on mac anyway) so that it can be run from the command line without the need to be in a specific directory or use the python command. You can even drop the .py from the file name so the user would just type in ?scorer? to start the script. If you?d like to make your script available to the wider community, you can put it on PyPI. See:?https://docs.python.org/2/distutils/packageindex.html ? Dylan Evans From anubhav1691 at gmail.com Tue Apr 7 10:31:21 2015 From: anubhav1691 at gmail.com (Anubhav Yadav) Date: Tue, 7 Apr 2015 14:01:21 +0530 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: You might consider packaging your project as a script so that it can be run > by the user from the command line. See: > https://docs.python.org/2/distutils/setupscript.html#installing-scripts > > Provided that you add something like #!/usr/bin/python to the top of > scorer.py, 'python setup.py install? will make it executable and move it to > /usr/local/bin (on mac anyway) so that it can be run from the command line > without the need to be in a specific directory or use the python command. > You can even drop the .py from the file name so the user would just type in > ?scorer? to start the script. > > Hi, as you can see my project doesn't have any single script. It is now made of many modules, and the app.py imports all the modules and executes them in the main() function. I also have an __main__.py where I call the main() function. I can run my project from the root of the directory using ``python -m scorer``. But if I use setuptools and install python using ``sudo python setup.py install``, setuptools says that my script is installed but I don't know how to run it? > If you?d like to make your script available to the wider community, you > can put it on PyPI. See: > https://docs.python.org/2/distutils/packageindex.html > I would love to upload my script to PyPi, but first I need to figure out if my project is getting installed properly using setuptools or not. -- Regards, Anubhav Yadav From emile at fenx.com Tue Apr 7 17:57:16 2015 From: emile at fenx.com (Emile van Sebille) Date: Tue, 07 Apr 2015 08:57:16 -0700 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: <5522E1B0.9070904@davea.name> References: <5522E1B0.9070904@davea.name> Message-ID: On 4/6/2015 12:42 PM, Dave Angel wrote: > On 04/06/2015 03:20 PM, Emile van Sebille wrote: >> Python 2.7.6 (default, Mar 22 2014, 22:59:56) >> [GCC 4.8.2] on linux2 >> Type "help", "copyright", "credits" or "license" for more information. >> >>> d = {'a':'123'} >> >>> def func(s=d['a']): >> ... print s >> ... >> >>> func() >> 123 >> > > Only if you know that nobody is going to be changing d. Clearly my example avoids the pitfalls of a changing d. :) > >>> d = {"a":"123"} > >>> def func(s=d["a"]): > ... print s > ... > >>> d["a"] = "new value" > >>> func() > 123 Good point -- I forgot about setting default parameters at compile time. >>> d={'a':'123'} >>> def func(s=d):print s['a'] ... >>> func() 123 >>> >>> d['a']='456' >>> func() 456 >>> From anubhav1691 at gmail.com Tue Apr 7 13:00:43 2015 From: anubhav1691 at gmail.com (Anubhav Yadav) Date: Tue, 7 Apr 2015 16:30:43 +0530 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: > > On your GitHub repository, you have a single file, scorer.py. I think that > this is a better approach in this instance than the multiple file approach > you have now taken (see below). > I am sorry I linked the master repository. See the structureCode branch[1]. > > > setuptools says that my script is installed but I don't know how to run > it? > > setuptools will have installed your module to site-packages so that other > developers can import it to use in writing their own code. However, your > code doesn?t provide anything for developers e.g. new functions, classes > etc. so this isn?t really want you want. Rather, your code should be run by > the end user, the cricket fan. From the first link I gave: > > ?Python modules...are usually not run by themselves but imported by > scripts. Scripts are files containing Python source code, intended to be > started from the command line" > > The latter sounds much more like your situation, so I recommend you do it > that way. Scripts like this should be single files, hence my recommendation > to use one file. > > Hope that helps, > This certainly helps, if you see the new link that I have given this time, you will notice that I have an app.py in my project dir, and it has the main() function. I have called the main function in __main__.py. This[2] blog post tells me that you can run your app using ``python -m scorer`` from the root directory of the project, and indeed I am able to run my scorer app like this. Now my question is how can I use setup tools so that users can just run "scorer" from the command line and the my script(which was installed before by setuptools) will start? [1] https://github.com/neo1691/scorer.py/tree/structureCode [2] http://blog.habnab.it/blog/2013/07/21/python-packages-and-you/ -- Regards, Anubhav Yadav KPIT Technologies, Pune. From anubhav1691 at gmail.com Tue Apr 7 17:50:54 2015 From: anubhav1691 at gmail.com (Anubhav Yadav) Date: Tue, 7 Apr 2015 21:20:54 +0530 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: I apologise, my method was for distutils, not setuptools. I get the two > muddled. The mechanism for creating a console script like you describe with > setuptools is described here[1]. The post you linked also has a section on > it under the heading ?Executable scripts?. It allows for the multiple file > approach you have. > > This is it, here's what I did: I edited my setup.py and added the following: entry_points={ 'console_scripts':[ 'scorer = scorer.app.main' ] }, As the main function is in scorer/app.py. Now after running sudo python setup.py install, I can see that there is a scorer binary installed in my system, but when I run that, I get the following error. Traceback (most recent call last): File "/usr/bin/scorer", line 9, in load_entry_point('scorer==0.1', 'console_scripts', 'scorer')() File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 546, in load_entry_point return get_distribution(dist).load_entry_point(group, name) File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2666, in load_entry_point return ep.load() File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2339, in load return self.resolve() File "/usr/lib/python2.7/site-packages/pkg_resources/__init__.py", line 2345, in resolve module = __import__(self.module_name, fromlist=['__name__'], level=0) ImportError: No module named main I am this close I guess! As an aside, I would also suggest that you look at PEP8, the Python style > guide[3]. Your code should really conform to it as much as possible. > And thanks a lot for giving me the PEP8 link, it will be helpful. > > [1] > https://pythonhosted.org/setuptools/setuptools.html#automatic-script-creation > [2] https://www.python.org/dev/peps/pep-0008/ > > > ? > > Dylan Evans > -- Regards, Anubhav Yadav KPIT Technologies, Pune. From fraghide at hotmail.it Tue Apr 7 22:52:07 2015 From: fraghide at hotmail.it (Francesca Ghidelli) Date: Tue, 7 Apr 2015 22:52:07 +0200 Subject: [Tutor] help Message-ID: Hello,First of all, i'm not trying to learn how to program with Python. I use Blender for my project, Blender 2.49b uses Python262. when i try to export the mesh from Blender to an other program, python doesn't work and show the error like the screenshot in annex. I've just installed numpy 1.3.0, but i tried different version before , it shows always the same error.I have Windows 7...could you find a solution for my problem? From alan.gauld at btinternet.com Wed Apr 8 01:23:07 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 08 Apr 2015 00:23:07 +0100 Subject: [Tutor] help In-Reply-To: References: Message-ID: On 07/04/15 21:52, Francesca Ghidelli wrote: > Hello,First of all, i'm not trying to learn how to program with Python. OK. So how exactly are you using Python? > I use Blender for my project, Blender 2.49b uses Python262. This is a list for folks learning Python so we don't necessarily know much about Blender. as I understand it Python is Blenders macro language. Is that what you are doing? Running a macro? > i try to export the mesh from Blender to an other program, What's a mesh? How does python feature in the export? > python doesn't work and show the error like the screenshot in annex. This is a mailing list. Many email gateways don't allow attachments. Your' got lost. Please copy the full error message into your post. If you can copy the code too - or at least the bit the error refers to - that would help - remember we don't know much about Blender. > I've just installed numpy 1.3.0, but i tried different version > before , it shows always the same error. Again, not too many here know numpy, it's not part of standard Python. How does it fit with Blender and your problem? If the error is a numpy error there is a numpy (or sciPy) list that might know more. There is also a mailing list on gmane.org that is dedicated to Python on Blender: gmane.comp.video.blender.python You could try asking there. They should at least understand what you are talking about. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cs at zip.com.au Wed Apr 8 02:11:30 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 8 Apr 2015 10:11:30 +1000 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: <20150408001130.GA106@cskk.homeip.net> On 07Apr2015 21:20, Anubhav Yadav wrote: >I apologise, my method was for distutils, not setuptools. I get the two >> muddled. The mechanism for creating a console script like you describe with >> setuptools is described here[1]. The post you linked also has a section on >> it under the heading ?Executable scripts?. It allows for the multiple file >> approach you have. >> >> This is it, here's what I did: > >I edited my setup.py and added the following: > entry_points={ > 'console_scripts':[ > 'scorer = scorer.app.main' > ] > }, My megacli module installs its "mcli" script like this: 'entry_points': { 'console_scripts': [ 'mcli = cs.app.megacli:main', ], Note the ":" before main, not ".". Cheers, Cameron Simpson I think... Therefore I ride. I ride... Therefore I am. - Mark Pope From robertvstepp at gmail.com Wed Apr 8 03:42:48 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Tue, 7 Apr 2015 20:42:48 -0500 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: <5522C872.7000003@davea.name> References: <5522B4D4.7060500@davea.name> <5522C872.7000003@davea.name> Message-ID: On Mon, Apr 6, 2015 at 12:54 PM, Dave Angel wrote: > On 04/06/2015 12:43 PM, boB Stepp wrote: > >> >> I was breaking down longer functions into smaller ones. Along the way >> I noticed I was passing an entire dictionary from one function to >> another. I only needed to pass one particular value, not the whole >> dictionary, so that is how I got into the issue I asked about. > > > Just to reinforce something you probably know well, passing a dictionary > takes no more memory or time than passing an item from that dictionary... One thing about Python that I must keep reminding myself is that its identifiers store references to objects, not the actual objects themselves. > ... The > real choice is whether the called function should dealing with a single item > or with a dictionary. It would have a different name in each case, and a > different set of reuse possibilities. In my actual code, I am trying to take advantage of these ideas. boB From robertvstepp at gmail.com Wed Apr 8 04:16:23 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Tue, 7 Apr 2015 21:16:23 -0500 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: <5522E1B0.9070904@davea.name> References: <5522E1B0.9070904@davea.name> Message-ID: On Mon, Apr 6, 2015 at 2:42 PM, Dave Angel wrote: > On 04/06/2015 03:20 PM, Emile van Sebille wrote: >> >> On 4/6/2015 7:54 AM, boB Stepp wrote: >>> [...] >> >> Maybe this form helps: >> >> Python 2.7.6 (default, Mar 22 2014, 22:59:56) >> [GCC 4.8.2] on linux2 >> Type "help", "copyright", "credits" or "license" for more information. >> >>> d = {'a':'123'} >> >>> def func(s=d['a']): >> ... print s >> ... >> >>> func() >> 123 >> > > Only if you know that nobody is going to be changing d. > >>>> d = {"a":"123"} >>>> def func(s=d["a"]): > ... print s > ... >>>> d["a"] = "new value" >>>> func() > 123 Despite Mark's warning, I feel I must see if I understand what is going on here. Switching to Py 3.4 since I am now at home: Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 64 bit (AMD64)] on win32 Type "copyright", "credits" or "license()" for more information. >>> d = {'a': '123'} >>> def func(s=d['a']): print(s) print(d['a']) >>> func() 123 123 >>> d['a'] = 'new value' >>> func() 123 new value I added an additional print to the function to show the dictionary entry's behavior. First, my current understanding is that this form of the function does not object to the presence of d['a'] in its parameter list because s is the real parameter, d['a'] is its default value, but s is not actually evaluated until run time. But once s *is* evaluated, it stores a reference to the original object, '123'. Changing d['a'] outside the function to a new value does not alter the fact that s is storing the very same reference to '123'. After reassigning d['a'] to point to the new object 'new value', a new call to func() shows s still referencing the original object and d['a'] referencing the new object. Is my comprehension of these details correct? If yes, this is why I must constantly remind myself that identifiers store references to objects, and that some objects are mutable and some aren't, and these Python facts of life are constantly challenging my old FORTRAN <= 77 ways of thinking... ~(:>)) -- boB From cs at zip.com.au Wed Apr 8 06:23:19 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 8 Apr 2015 14:23:19 +1000 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: Message-ID: <20150408042319.GA42297@cskk.homeip.net> On 08Apr2015 08:53, Anubhav Yadav wrote: >>Note the ":" before main, not ".". > >That's it, that fixed the problem. Now I have a scorer binary. No, you have a "scorer" executable which is a script. A "binary" is a loadable machine code file. >Thanks. A >couple of more questions! > >1) If I have install_requires in setup.py, then do I need requirements.txt? Probably not? I don't use this yet myself. >2) Can I run ``python setup.py install`` or ``python setup.py develop`` >with root privileges? Just to test the app first? Yes, but I would discourage it. It is too easy to tread on your platform's supplier packages this way. That can be bad, especially if you break something important for your OS. Instead, I would advocate making a virtualenv iin your home directory into which you install your packages. You can make as many as you like. After you've made a virtualenv, running the "pip" it supplies will install into the virtualenv. Much safer, and you can do it all as yourself. Cheers, Cameron Simpson I made this letter longer than usual because I lack the time to make it shorter. - Pascal From cs at zip.com.au Wed Apr 8 06:43:22 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 8 Apr 2015 14:43:22 +1000 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: Message-ID: <20150408044322.GA67698@cskk.homeip.net> On 07Apr2015 21:16, boB Stepp wrote: >Despite Mark's warning, I feel I must see if I understand what is going on here. > >Switching to Py 3.4 since I am now at home: > >Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 >64 bit (AMD64)] on win32 >Type "copyright", "credits" or "license()" for more information. >>>> d = {'a': '123'} >>>> def func(s=d['a']): > print(s) > print(d['a']) > >>>> func() >123 >123 >>>> d['a'] = 'new value' >>>> func() >123 >new value > >I added an additional print to the function to show the dictionary >entry's behavior. > >First, my current understanding is that this form of the function does >not object to the presence of d['a'] in its parameter list because s >is the real parameter, d['a'] is its default value, but s is not >actually evaluated until run time. Yes and no. Yes to "s is the real parameter, d['a'] is its default value". No to "s is not actually evaluated until run time". When you _define_ the function, the _current_ value of d['a'] is stashed in the function definition as the default value. When you _call_ the function, and omit the 's' parameter, the default value is used. However, that value was _computed_ when the function was compiled: the function definition does not keep "d['a']" around for evaluation, instead that expression is evaluated when you define the function, and the reference to the resulting value kept around. That is thus '123'. So when you go: d['a'] = 'new value' the contents of the "d" dictionary have changed. But all that has happened is that the reference to '123' is no longer in the dictionary; instead a reference to 'new value' is in the dictionary. When you call "func()" the name "s" is bound to the default value, which is the '123' as computed at function definition time. And it prints that. Of course, when you print "d['a']" it must evaluate that then, and finds 'new value'. This is one reason why the common idion for default values looks like this: def func(s=None): if s is None: s = ... compute default here ... Of course, the default is often a constant or some value computed earlier. Cheers, Cameron Simpson I think... Therefore I ride. I ride... Therefore I am. - Mark Pope From anubhav1691 at gmail.com Wed Apr 8 05:23:11 2015 From: anubhav1691 at gmail.com (Anubhav Yadav) Date: Wed, 8 Apr 2015 08:53:11 +0530 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: <20150408001130.GA106@cskk.homeip.net> References: <20150408001130.GA106@cskk.homeip.net> Message-ID: Note the ":" before main, not ".". > That's it, that fixed the problem. Now I have a scorer binary. Thanks. A couple of more questions! 1) If I have install_requires in setup.py, then do I need requirements.txt? 2) Can I run ``python setup.py install`` or ``python setup.py develop`` with root privileges? Just to test the app first? -- Regards, Anubhav Yadav Pune. From anubhav1691 at gmail.com Wed Apr 8 08:28:54 2015 From: anubhav1691 at gmail.com (Anubhav Yadav) Date: Wed, 8 Apr 2015 11:58:54 +0530 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: <20150408042319.GA42297@cskk.homeip.net> References: <20150408042319.GA42297@cskk.homeip.net> Message-ID: > Instead, I would advocate making a virtualenv iin your home directory into > which you install your packages. You can make as many as you like. > > After you've made a virtualenv, running the "pip" it supplies will install > into the virtualenv. Much safer, and you can do it all as yourself. > Thanks a lot, I would now spend some time learning virtualenv! This has really helped me. Thank you everyone again for helping me out. I would bring the thread alive again if I am stuck somewhere. Cheers Regards, Anubhav Yadav Pune. From cybervigilante at gmail.com Wed Apr 8 02:52:19 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Tue, 7 Apr 2015 17:52:19 -0700 Subject: [Tutor] migrating python to a new machine Message-ID: General question. I'm thinking of moving to a new machine although I hate to abandon trusty XP. Will I have to reinstall all my pip installed modules or can I just copy the site-packages directory? And if so, is anything else needed, such as where pip keeps its uninstall info? Finally, is there such a thing as a standalone Python? I use a number of standalone programs so it seems to me it should be possible. -- Jim "Stop, Harold! That bagel has radishes!" "Thank God, Mary - you've saved me again!" From alan.gauld at btinternet.com Wed Apr 8 09:50:53 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 08 Apr 2015 08:50:53 +0100 Subject: [Tutor] migrating python to a new machine In-Reply-To: References: Message-ID: On 08/04/15 01:52, Jim Mooney wrote: > General question. I'm thinking of moving to a new machine although I hate > to abandon trusty XP. If you plan to stick with Windows check out ClassicShell. You'll feel right at home. :-) > Will I have to reinstall all my pip installed modules > or can I just copy the site-packages directory? I think that will work. You will need to reinstall Python itself to get the registry set up but I think the stuff that Python installs is safe to just copy across. > Finally, is there such a thing as a standalone Python? I'm not sure what you mean by that. But if its a Python that you can install/run on a USB stick, say, then yes, there are several options available. Google is your friend... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Wed Apr 8 09:54:19 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 08 Apr 2015 08:54:19 +0100 Subject: [Tutor] Need some help with setuptools for my project. In-Reply-To: References: <20150408042319.GA42297@cskk.homeip.net> Message-ID: On 08/04/15 07:28, Anubhav Yadav wrote: > really helped me. Thank you everyone again for helping me out. I would > bring the thread alive again if I am stuck somewhere. Please don't! If it's a new problem start a new thread with new subject line. 1) The old thread will be miles back in the history and invisible to anyone using a threaded reader. 2) Anyone searching the archives will find it difficult to see your new issue buried inside a previous thread -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From zachary.ware+pytut at gmail.com Wed Apr 8 13:44:42 2015 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Wed, 8 Apr 2015 06:44:42 -0500 Subject: [Tutor] migrating python to a new machine In-Reply-To: References: Message-ID: On Apr 8, 2015 3:39 AM, "Jim Mooney" wrote: > > General question. I'm thinking of moving to a new machine although I hate > to abandon trusty XP. Will I have to reinstall all my pip installed modules > or can I just copy the site-packages directory? And if so, is anything else > needed, such as where pip keeps its uninstall info? The safest method would probably be to do `pip freeze > requirements.txt`, copy the requirements.txt file to the new machine, and run `pip install -r requirements.txt` there. That way you definitely get everything (and you can save the requirements file for backup purposes). > Finally, is there such a thing as a standalone Python? I use a number of > standalone programs so it seems to me it should be possible. Do you mean like a "portable" app, that doesn't write to the registry and keeps everything in one folder? You can try PortablePython; I used it some several years ago and it seemed to work fine (but that was when I was just starting with Python). Hope this helps, -- Zach From davea at davea.name Wed Apr 8 14:44:22 2015 From: davea at davea.name (Dave Angel) Date: Wed, 08 Apr 2015 08:44:22 -0400 Subject: [Tutor] Why is it invalid syntax to have a particular dictionary value as an argument? In-Reply-To: References: <5522E1B0.9070904@davea.name> Message-ID: <552522A6.9010406@davea.name> On 04/07/2015 10:16 PM, boB Stepp wrote: > > Despite Mark's warning, I feel I must see if I understand what is going on here. > > Switching to Py 3.4 since I am now at home: > > Python 3.4.3 (v3.4.3:9b73f1c3e601, Feb 24 2015, 22:44:40) [MSC v.1600 > 64 bit (AMD64)] on win32 > Type "copyright", "credits" or "license()" for more information. >>>> d = {'a': '123'} >>>> def func(s=d['a']): > print(s) > print(d['a']) > >>>> func() > 123 > 123 >>>> d['a'] = 'new value' >>>> func() > 123 > new value > > I added an additional print to the function to show the dictionary > entry's behavior. > > First, my current understanding is that this form of the function does > not object to the presence of d['a'] in its parameter list because s > is the real parameter, d['a'] is its default value, but s is not > actually evaluated until run time. s is not evaluated till the print statement. s is *bound* at function call time. And at that time it is either bound to the object passed by the caller, or to the default object. In a simple assignment statement: a = b + 6 the expression on the right is evaluated. The name on the left is not evaluated, it is bound to. So we say "a is bound to the result of the expression b+6" > > But once s *is* evaluated, it stores a reference to the original s is bound to the expression ''default_object'', which is to say it copies the same reference that the default object stored earlier. So it is bound to '123' > object, '123'. Changing d['a'] outside the function to a new value > does not alter the fact that s is storing the very same reference to > '123'. After reassigning d['a'] to point to the new object 'new > value', a new call to func() shows s still referencing the original > object and d['a'] referencing the new object. Is my comprehension of > these details correct? If yes, this is why I must constantly remind > myself that identifiers store references to objects, and that some > objects are mutable and some aren't, and these Python facts of life > are constantly challenging my old FORTRAN <= 77 ways of thinking... > ~(:>)) > -- DaveA From cybervigilante at gmail.com Wed Apr 8 17:25:45 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Wed, 8 Apr 2015 08:25:45 -0700 Subject: [Tutor] migrating python to a new machine In-Reply-To: References: Message-ID: Thanks, I'll try Portable. It's got py3 and comes with a bunch of useful stuff already installed: http://portablepython.com/wiki/PortablePython3.2.5.1/ Python 3.2.5.1 PyScripter v2.5.3 NymPy 1.7.1 SciPy 0.12.0 Matplotlib 1.2.1 PyWin32 218 NetworkX v1.7 Lxml 2.3 PySerial 2.5 PyODBC 3.0.2 PyQt 4.9.6-1 IPython 0.13.1 Pandas 0.11.0 On 8 April 2015 at 04:44, Zachary Ware wrote: > On Apr 8, 2015 3:39 AM, "Jim Mooney" wrote: > > > > General question. I'm thinking of moving to a new machine although I hate > > to abandon trusty XP. Will I have to reinstall all my pip installed > modules > > or can I just copy the site-packages directory? And if so, is anything > else > > needed, such as where pip keeps its uninstall info? > > The safest method would probably be to do `pip freeze > requirements.txt`, > copy the requirements.txt file to the new machine, and run `pip install -r > requirements.txt` there. That way you definitely get everything (and you > can save the requirements file for backup purposes). > > > Finally, is there such a thing as a standalone Python? I use a number of > > standalone programs so it seems to me it should be possible. > > Do you mean like a "portable" app, that doesn't write to the registry and > keeps everything in one folder? You can try PortablePython; I used it some > several years ago and it seemed to work fine (but that was when I was just > starting with Python). > > Hope this helps, > -- > Zach > -- Jim "Stop, Harold! That bagel has radishes!" "Thank God, Mary - you've saved me again!" From akleider at sonic.net Thu Apr 9 04:44:39 2015 From: akleider at sonic.net (Alex Kleider) Date: Wed, 08 Apr 2015 19:44:39 -0700 Subject: [Tutor] pip install lxml fails Message-ID: In the process of trying to learn about web scraping (http://docs.python-guide.org/en/latest/scenarios/scrape/) I tried to pip install lxml. Can anyone suggest a remedy? The output goes on for many pages and the resulting .pip/pip.log file is almost 900 lines long but the main meat of the failure seems to be in the following: (env)alex at t61p:~/P3env/declination.d$ pip install lxml Downloading/unpacking lxml Downloading lxml-3.4.2.tar.gz (3.5MB): 3.5MB downloaded Running setup.py (path:/home/alex/P3env/env/build/lxml/setup.py) egg_info for package lxml Building lxml version 3.4.2. Building without Cython. Using build configuration of libxslt 1.1.28 /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'bugtrack_url' warnings.warn(msg) warning: no previously-included files found matching '*.py' Installing collected packages: lxml Running setup.py install for lxml Building lxml version 3.4.2. Building without Cython. Using build configuration of libxslt 1.1.28 building 'lxml.etree' extension i686-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/libxml2 -I/home/alex/P3env/env/build/lxml/src/lxml/includes -I/usr/include/python3.4m -I/home/alex/P3env/env/include/python3.4m -c src/lxml/lxml.etree.c -o build/temp.linux-i686-3.4/src/lxml/lxml.etree.o -w src/lxml/lxml.etree.c:8:22: fatal error: pyconfig.h: No such file or directory #include "pyconfig.h" ^ compilation terminated. /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'bugtrack_url' warnings.warn(msg) error: command 'i686-linux-gnu-gcc' failed with exit status 1 Complete output from command /home/alex/P3env/env/bin/python3 -c "import setuptools, tokenize;__file__='/home/alex/P3env/env/build/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-sknxo73w-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/alex/P3env/env/include/site/python3.4: ...... From akleider at sonic.net Thu Apr 9 17:29:46 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 09 Apr 2015 08:29:46 -0700 Subject: [Tutor] pip install lxml fails In-Reply-To: <20150409140818.GB6451@test-chamber-1.castopulence.org> References: <20150409140818.GB6451@test-chamber-1.castopulence.org> Message-ID: On 2015-04-09 07:08, Brandon McCaig wrote: > I'm a python newbie, but it looks to me like your compiler cannot > find your header files, and in particular pyconfig.h. > > I tried searching my system and found a file with that name at > these locations: > > /home/bambams/src/pyenv/versions/2.7.9/include/python2.7/pyconfig.h > > /home/bambams/src/pyenv/versions/3.4.2/include/python3.4m/pyconfig.h > /usr/include/python2.6/pyconfig.h > /usr/include/python2.7/pyconfig.h > /usr/include/python3.2mu/pyconfig.h > > Based on that I am assuming that you should have a pyconfig.h in > either /usr/include/python3.4m or > /home/alex/P3env/env/include/python3.4m. I would probably start > there to verify that I have that header file in a location where > it's expected (-I flags in the above command, or system include > directories). If not then I would wonder why... > > Regards, Thank you very much for looking into this. I have corresponding files in /usr/include for 2.7 but not for 3*: alex at t61p:~/P3env/env$ ls -ld /usr/include/python* drwxr-xr-x 2 root root 4096 Apr 8 19:05 /usr/include/python2.7 alex at t61p:~/P3env/env$ ls bin lib Nothing in the env file (generated by virtualenv.) My Ubuntu 14.04 system comes with Python3 by default so it does exist: alex at t61p:~/P3env/env$ which python3 /usr/bin/python3 It's a mystery why it doesn't come with the corresponding include directory. I'm guessing this is a system level problem that can probably only be solved by someone at Ubuntu or one of the lxml maintainers. Thanks again, Alex From stefan_ml at behnel.de Thu Apr 9 18:11:25 2015 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 09 Apr 2015 18:11:25 +0200 Subject: [Tutor] pip install lxml fails In-Reply-To: References: <20150409140818.GB6451@test-chamber-1.castopulence.org> Message-ID: Alex Kleider schrieb am 09.04.2015 um 17:29: > On 2015-04-09 07:08, Brandon McCaig wrote: >> I'm a python newbie, but it looks to me like your compiler cannot >> find your header files, and in particular pyconfig.h. >> >> I tried searching my system and found a file with that name at >> these locations: >> >> /home/bambams/src/pyenv/versions/2.7.9/include/python2.7/pyconfig.h >> /home/bambams/src/pyenv/versions/3.4.2/include/python3.4m/pyconfig.h >> /usr/include/python2.6/pyconfig.h >> /usr/include/python2.7/pyconfig.h >> /usr/include/python3.2mu/pyconfig.h >> >> Based on that I am assuming that you should have a pyconfig.h in >> either /usr/include/python3.4m or >> /home/alex/P3env/env/include/python3.4m. I would probably start >> there to verify that I have that header file in a location where >> it's expected (-I flags in the above command, or system include >> directories). If not then I would wonder why... > > I have corresponding files in /usr/include for 2.7 but not for 3*: > alex at t61p:~/P3env/env$ ls -ld /usr/include/python* > drwxr-xr-x 2 root root 4096 Apr 8 19:05 /usr/include/python2.7 > > alex at t61p:~/P3env/env$ ls > bin lib > Nothing in the env file (generated by virtualenv.) > > My Ubuntu 14.04 system comes with Python3 by default so it does exist: > alex at t61p:~/P3env/env$ which python3 > /usr/bin/python3 > It's a mystery why it doesn't come with the corresponding include directory. > > I'm guessing this is a system level problem that can probably only be > solved by someone at Ubuntu or one of the lxml maintainers. It's solved already. :) All you need to do is install the "-dev" package that goes with your Python installation, e.g. "python3-dev" should match Python 3.4 in current Ubuntu releases. The reason why it's in a separate package is that many people actually don't need this, e.g. when they only install plain Python packages or use the Ubuntu provided binary packages that they can install via apt (e.g. "sudo apt-get install python-lxml"). Stefan From akleider at sonic.net Thu Apr 9 21:49:16 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 09 Apr 2015 12:49:16 -0700 Subject: [Tutor] pip install lxml fails In-Reply-To: References: <20150409140818.GB6451@test-chamber-1.castopulence.org> Message-ID: <957838078c7c686d7e635054e832eba5@sonic.net> On 2015-04-09 09:11, Stefan Behnel wrote: > It's solved already. :) > > All you need to do is install the "-dev" package that goes with your > Python > installation, e.g. "python3-dev" should match Python 3.4 in current > Ubuntu > releases. > > The reason why it's in a separate package is that many people actually > don't need this, e.g. when they only install plain Python packages or > use > the Ubuntu provided binary packages that they can install via apt (e.g. > "sudo apt-get install python-lxml"). Thanks Brandon and Sefan. It proved correct that I did not have python3-dev installed .. but after intalling it, the pip install lxml still fails! There's a huge amount of output but what follows might provide clues as to the current problem: ................ /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'bugtrack_url' warnings.warn(msg) warning: no previously-included files found matching '*.py' ....... Cleaning up... Command /home/alex/P3env/env/bin/python3 -c "import setuptools, tokenize;__file__='/home/alex/P3env/env/build/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-56yiw_ye-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/alex/P3env/env/include/site/python3.4 failed with error code 1 in /home/alex/P3env/env/build/lxml Storing debug log for failure in /home/alex/.pip/pip.log Looking at ~/.pip/pip.log there seem to be hundreds of Skipping link ... unknown archive format: .egg, .exe, lines typified by the following two: Skipping link https://pypi.python.org/packages/2.7/l/lxml/lxml-2.3beta1-py2.7-win32.egg#md5=4c0da2b308dd2cd0095de21c26647842 (from https://pypi.python.org/simple/lxml/); unknown archive format: .egg Skipping link https://pypi.python.org/packages/2.7/l/lxml/lxml-2.3beta1.win32-py2.7.exe#md5=ea0224feed6f649cdb1ccb656ab91d81 (from https://pypi.python.org/simple/lxml/); unknown archive format: .exe Then it found some tar.gz links (103 of them to be exact) Then "Ignoring link .." for bout 27 lines and finally Some possibly useful information: Using version 3.4.2 (newest of versions: 3.4.2, 3.4.1, 3.4.0, 3.3.6, 3.3.5, 3.3.4, 3.3.3, 3.3.2, 3.3.1, 3.3.0, 3.2.5, 3.2.4, 3.2.3, 3.2.2, 3.2.1, 3.2.0, 3.1.2, 3.1.1, 3.1.0, 3.0.2, 3.0.1, 3.0, 2.3.6, 2.3.5, 2.3.4, 2.3.3, 2.3.2, 2.3.1, 2.3, 2.2.8, 2.2.7, 2.2.6, 2.2.5, 2.2.4, 2.2.3, 2.2.2, 2.2.1, 2.2, 2.1.5, 2.1.4, 2.1.3, 2.1.2, 2.1.1, 2.1, 2.0.11, 2.0.10, 2.0.9, 2.0.8, 2.0.7, 2.0.6, 2.0.5, 2.0.4, 2.0.3, 2.0.2, 2.0.1, 2.0, 1.3.6, 1.3.5, 1.3.4, 1.3.3, 1.3.2, 1.3, 1.2.1, 1.2, 1.1.2, 1.1.1, 1.1, 1.0.4, 1.0.3, 1.0.2, 1.0.1, 1.0, 0.9.2, 0.9.1, 0.9) Downloading from URL https://pypi.python.org/packages/source/l/lxml/lxml-3.4.2.tar.gz#md5=429e5e771c4be0798923c04cb9739b4e (from https://pypi.python.org/simple/lxml/) Running setup.py (path:/home/alex/P3env/env/build/lxml/setup.py) egg_info for package lxml Building lxml version 3.4.2. Building without Cython. Using build configuration of libxslt 1.1.28 running egg_info creating pip-egg-info/lxml.egg-info writing pip-egg-info/lxml.egg-info/PKG-INFO writing dependency_links to pip-egg-info/lxml.egg-info/dependency_links.txt writing top-level names to pip-egg-info/lxml.egg-info/top_level.txt writing requirements to pip-egg-info/lxml.egg-info/requires.txt writing manifest file 'pip-egg-info/lxml.egg-info/SOURCES.txt' /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'bugtrack_url' warnings.warn(msg) warning: manifest_maker: standard file '-c' not found .......... i686-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/libxml2 -I/home/alex/P3env/env/build/lxml/src/lxml/includes -I/usr/include/python3.4m -I/home/alex/P3env/env/include/python3.4m -c src/lxml/lxml.etree.c -o build/temp.linux-i686-3.4/src/lxml/lxml.etree.o -w i686-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 build/temp.linux-i686-3.4/src/lxml/lxml.etree.o -lxslt -lexslt -lxml2 -lz -lm -o build/lib.linux-i686-3.4/lxml/etree.cpython-34m.so /usr/bin/ld: cannot find -lz collect2: error: ld returned 1 exit status /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'bugtrack_url' warnings.warn(msg) error: command 'i686-linux-gnu-gcc' failed with exit status 1 Complete output from command /home/alex/P3env/env/bin/python3 -c "import setuptools, tokenize;__file__='/home/alex/P3env/env/build/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-56yiw_ye-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/alex/P3env/env/include/site/python3.4: Building lxml version 3.4.2. Building without Cython. Using build configuration of libxslt 1.1.28 running install running build running build_py creating build .......... i686-linux-gnu-gcc -pthread -DNDEBUG -g -fwrapv -O2 -Wall -Wstrict-prototypes -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 -fPIC -I/usr/include/libxml2 -I/home/alex/P3env/env/build/lxml/src/lxml/includes -I/usr/include/python3.4m -I/home/alex/P3env/env/include/python3.4m -c src/lxml/lxml.etree.c -o build/temp.linux-i686-3.4/src/lxml/lxml.etree.o -w i686-linux-gnu-gcc -pthread -shared -Wl,-O1 -Wl,-Bsymbolic-functions -Wl,-Bsymbolic-functions -Wl,-z,relro -Wl,-Bsymbolic-functions -Wl,-z,relro -g -fstack-protector --param=ssp-buffer-size=4 -Wformat -Werror=format-security -D_FORTIFY_SOURCE=2 build/temp.linux-i686-3.4/src/lxml/lxml.etree.o -lxslt -lexslt -lxml2 -lz -lm -o build/lib.linux-i686-3.4/lxml/etree.cpython-34m.so /usr/bin/ld: cannot find -lz collect2: error: ld returned 1 exit status /usr/lib/python3.4/distutils/dist.py:260: UserWarning: Unknown distribution option: 'bugtrack_url' warnings.warn(msg) error: command 'i686-linux-gnu-gcc' failed with exit status 1 ---------------------------------------- Cleaning up... Removing temporary dir /home/alex/P3env/env/build... Command /home/alex/P3env/env/bin/python3 -c "import setuptools, tokenize;__file__='/home/alex/P3env/env/build/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-56yiw_ye-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/alex/P3env/env/include/site/python3.4 failed with error code 1 in /home/alex/P3env/env/build/lxml Exception information: Traceback (most recent call last): File "/home/alex/P3env/env/lib/python3.4/site-packages/pip/basecommand.py", line 122, in main status = self.run(options, args) File "/home/alex/P3env/env/lib/python3.4/site-packages/pip/commands/install.py", line 283, in run requirement_set.install(install_options, global_options, root=options.root_path) File "/home/alex/P3env/env/lib/python3.4/site-packages/pip/req.py", line 1435, in install requirement.install(install_options, global_options, *args, **kwargs) File "/home/alex/P3env/env/lib/python3.4/site-packages/pip/req.py", line 706, in install cwd=self.source_dir, filter_stdout=self._filter_install, show_stdout=False) File "/home/alex/P3env/env/lib/python3.4/site-packages/pip/util.py", line 697, in call_subprocess % (command_desc, proc.returncode, cwd)) pip.exceptions.InstallationError: Command /home/alex/P3env/env/bin/python3 -c "import setuptools, tokenize;__file__='/home/alex/P3env/env/build/lxml/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-56yiw_ye-record/install-record.txt --single-version-externally-managed --compile --install-headers /home/alex/P3env/env/include/site/python3.4 failed with error code 1 in /home/alex/P3env/env/build/lxml From stefan_ml at behnel.de Thu Apr 9 22:10:50 2015 From: stefan_ml at behnel.de (Stefan Behnel) Date: Thu, 09 Apr 2015 22:10:50 +0200 Subject: [Tutor] pip install lxml fails In-Reply-To: <957838078c7c686d7e635054e832eba5@sonic.net> References: <20150409140818.GB6451@test-chamber-1.castopulence.org> <957838078c7c686d7e635054e832eba5@sonic.net> Message-ID: Alex Kleider schrieb am 09.04.2015 um 21:49: > On 2015-04-09 09:11, Stefan Behnel wrote: >> All you need to do is install the "-dev" package that goes with your Python >> installation, e.g. "python3-dev" should match Python 3.4 in current Ubuntu >> releases. >> >> The reason why it's in a separate package is that many people actually >> don't need this, e.g. when they only install plain Python packages or use >> the Ubuntu provided binary packages that they can install via apt (e.g. >> "sudo apt-get install python-lxml"). > > Thanks Brandon and Sefan. It proved correct that I did not have > python3-dev installed > .. but after intalling it, the pip install lxml still fails! > > There's a huge amount of output but what follows might provide clues as to > the current problem: > [...] > /usr/bin/ld: cannot find -lz Same thing, you need to make zlib available to the build. Ubuntu calls the package "zlib1g-dev". And while you're at it, make sure you also have "libxml2-dev" and "libxslt-dev". The official installation instructions can be found here, BTW: http://lxml.de/installation.html Stefan From __peter__ at web.de Thu Apr 9 22:26:46 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 09 Apr 2015 22:26:46 +0200 Subject: [Tutor] pip install lxml fails References: <20150409140818.GB6451@test-chamber-1.castopulence.org> <957838078c7c686d7e635054e832eba5@sonic.net> Message-ID: Stefan Behnel wrote: > Alex Kleider schrieb am 09.04.2015 um 21:49: >> On 2015-04-09 09:11, Stefan Behnel wrote: >>> All you need to do is install the "-dev" package that goes with your >>> Python installation, e.g. "python3-dev" should match Python 3.4 in >>> current Ubuntu releases. >>> >>> The reason why it's in a separate package is that many people actually >>> don't need this, e.g. when they only install plain Python packages or >>> use the Ubuntu provided binary packages that they can install via apt >>> (e.g. "sudo apt-get install python-lxml"). >> >> Thanks Brandon and Sefan. It proved correct that I did not have >> python3-dev installed >> .. but after intalling it, the pip install lxml still fails! >> >> There's a huge amount of output but what follows might provide clues as >> to the current problem: >> [...] >> /usr/bin/ld: cannot find -lz > > Same thing, you need to make zlib available to the build. Ubuntu calls the > package "zlib1g-dev". And while you're at it, make sure you also have > "libxml2-dev" and "libxslt-dev". > > The official installation instructions can be found here, BTW: > > http://lxml.de/installation.html I'd try $ sudo apt-get build-dep python3-lxml This should install all build dependencies of the python3-lxml package which are likely the same as those of a manual installation of lxml. From akleider at sonic.net Thu Apr 9 22:27:37 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 09 Apr 2015 13:27:37 -0700 Subject: [Tutor] pip install lxml fails In-Reply-To: <957838078c7c686d7e635054e832eba5@sonic.net> References: <20150409140818.GB6451@test-chamber-1.castopulence.org> <957838078c7c686d7e635054e832eba5@sonic.net> Message-ID: I tried something different and although not successful, there seems to be some progress: ---------------------------------------- (env)alex at t61p:~/P3env$ CFLAGS="-O0" STATIC_DEPS=true pip install lxml ..... Exception: Command "make -j3" returned code 512 ---------------------------------------- Cleaning up... Command python setup.py egg_info failed with error code 1 in /home/alex/P3env/env/build/lxml Storing debug log for failure in /home/alex/.pip/pip.log The part of .pip/pip.log that might prove useful is as follows: make[1]: Leaving directory `/home/alex/P3env/env/build/lxml/build/tmp/libiconv-1.14/srclib' make: *** [all] Error 2 Building lxml version 3.4.2. Latest version of libiconv is 1.14 Downloading libiconv into libs/libiconv-1.14.tar.gz Unpacking libiconv-1.14.tar.gz into build/tmp Latest version of libxml2 is 2.9.2 Downloading libxml2 into libs/libxml2-2.9.2.tar.gz Unpacking libxml2-2.9.2.tar.gz into build/tmp Latest version of libxslt is 1.1.28 Downloading libxslt into libs/libxslt-1.1.28.tar.gz Unpacking libxslt-1.1.28.tar.gz into build/tmp Starting build in build/tmp/libiconv-1.14 Traceback (most recent call last): File "", line 17, in File "/home/alex/P3env/env/build/lxml/setup.py", line 230, in **setup_extra_options() File "/home/alex/P3env/env/build/lxml/setup.py", line 144, in setup_extra_options STATIC_CFLAGS, STATIC_BINARIES) File "/home/alex/P3env/env/build/lxml/setupinfo.py", line 57, in ext_modules multicore=OPTION_MULTICORE) File "/home/alex/P3env/env/build/lxml/buildlibxml.py", line 348, in build_libxml2xslt cmmi(configure_cmd, libiconv_dir, multicore, **call_setup) File "/home/alex/P3env/env/build/lxml/buildlibxml.py", line 285, in cmmi cwd=build_dir, **call_setup) File "/home/alex/P3env/env/build/lxml/buildlibxml.py", line 268, in call_subprocess raise Exception('Command "%s" returned code %s' % (cmd_desc, returncode)) Exception: Command "make -j3" returned code 512 Complete output from command python setup.py egg_info: checking for a BSD-compatible install... /usr/bin/install -c checking whether build environment is sane... yes .... From akleider at sonic.net Thu Apr 9 22:40:57 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 09 Apr 2015 13:40:57 -0700 Subject: [Tutor] pip install lxml fails In-Reply-To: References: <20150409140818.GB6451@test-chamber-1.castopulence.org> <957838078c7c686d7e635054e832eba5@sonic.net> Message-ID: On 2015-04-09 13:26, Peter Otten wrote: > I'd try > > $ sudo apt-get build-dep python3-lxml build-dep is not an apt-get command I've seen before but it did the trick! > > This should install all build dependencies of the python3-lxml package > which > are likely the same as those of a manual installation of lxml. I can now import lxml Thank you very much, indeed! Alex From cybervigilante at gmail.com Thu Apr 9 21:02:22 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 9 Apr 2015 12:02:22 -0700 Subject: [Tutor] annoying directory structure Message-ID: "The safest method would probably be to do `pip freeze > requirements.txt`, copy the requirements.txt file to the new machine, and run `pip install -r requirements.txt" --Zach I looked at pip3 help (windows) and don't see a -r command. However, it does work. How do I get the "invisible" commands ;') Another question. I have a set of training vids. Unfortunately, each vid is in a subdir inside a subdir inside a subdir inside a subdir inside the directory. Going down, down, down, up, up, up to nab them (they're short) and remember where I am, is annoying. How do I use python to get a simple straight list of the vids in directory order - full windows path - so I can just copy and plug the paths into windows explorer, one at a time? -- Jim Guido van Rossum fan club and coffee bar looking for baristas who know Python From zachary.ware+pytut at gmail.com Thu Apr 9 23:01:00 2015 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Thu, 9 Apr 2015 16:01:00 -0500 Subject: [Tutor] annoying directory structure In-Reply-To: References: Message-ID: On Thu, Apr 9, 2015 at 2:02 PM, Jim Mooney wrote: > "The safest method would probably be to do `pip freeze > requirements.txt`, > copy the requirements.txt file to the new machine, and run `pip install -r > requirements.txt" --Zach > > I looked at pip3 help (windows) and don't see a -r command. However, it > does work. How do I get the "invisible" commands ;') Try `pip3 help install` :) > Another question. I have a set of training vids. Unfortunately, each vid is > in a subdir inside a subdir inside a subdir inside a subdir inside the > directory. Going down, down, down, up, up, up to nab them (they're short) > and remember where I am, is annoying. How do I use python to get a simple > straight list of the vids in directory order - full windows path - so I can > just copy and plug the paths into windows explorer, one at a time? Have a look at os.walk(), it will enable you to walk (hence the name) through all directories in a tree. Take a crack at it, and if you have trouble come back with some code for us to look at. You may also need os.path.abspath to get the full path. -- Zach From cybervigilante at gmail.com Fri Apr 10 00:17:51 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 9 Apr 2015 15:17:51 -0700 Subject: [Tutor] annoying directory structure In-Reply-To: References: Message-ID: Looks like I can work it, but some walk paths are coming out as two strings back to back, which I know python concatenates with print, but how do I concatenate them without print so I can use them in my script to append to the mp4 filenames and have a windows readable path?. i.e., I am getting this sort of triplet when I go through the generator. After doing that the rest seems easy enough: A = ('I:\\VIDS\\Learn Python Track\\07. Regular Expressions in Python\\Stage ' '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops', [], ['Compiling and Loops.mp4', 'Compiling and Loops.srt']) >> A[0] ('I:\\VIDS\\Learn Python Track\\07. Regular Expressions in Python\\Stage ' '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops') Still two unconcatenated strings And why do I still have tuple parentheses for A[0], which should be a concatenated string? > > Another question. I have a set of training vids. Unfortunately, each vid > is > > in a subdir inside a subdir inside a subdir inside a subdir inside the > > directory. Going down, down, down, up, up, up to nab them (they're short) > > and remember where I am, is annoying. How do I use python to get a simple > > straight list of the vids in directory order - full windows path - so I > can > > just copy and plug the paths into windows explorer, one at a time? > > Have a look at os.walk(), it will enable you to walk (hence the name) > through all directories in a tree. Take a crack at it, and if you > have trouble come back with some code for us to look at. You may also > need os.path.abspath to get the full path. > > -- > Zach > -- Jim "Stop, Harold! That bagel has radishes!" "Thank God, Mary - you've saved me again!" From zachary.ware+pytut at gmail.com Fri Apr 10 01:31:49 2015 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Thu, 9 Apr 2015 18:31:49 -0500 Subject: [Tutor] annoying directory structure In-Reply-To: References: Message-ID: (Please use a bottom-posting/interleaved style of reply on this list, it makes conversations much easier to follow. I've fixed your message in my response below.) On Thu, Apr 9, 2015 at 5:17 PM, Jim Mooney wrote: >> > Another question. I have a set of training vids. Unfortunately, each vid >> is >> > in a subdir inside a subdir inside a subdir inside a subdir inside the >> > directory. Going down, down, down, up, up, up to nab them (they're short) >> > and remember where I am, is annoying. How do I use python to get a simple >> > straight list of the vids in directory order - full windows path - so I >> can >> > just copy and plug the paths into windows explorer, one at a time? >> >> Have a look at os.walk(), it will enable you to walk (hence the name) >> through all directories in a tree. Take a crack at it, and if you >> have trouble come back with some code for us to look at. You may also >> need os.path.abspath to get the full path. > > Looks like I can work it, but some walk paths are coming out as two strings > back to back, which I know python concatenates with print, but how do I > concatenate them without print so I can use them in my script to append to > the mp4 filenames and have a windows readable path?. i.e., I am getting > this sort of triplet when I go through the generator. After doing that the > rest seems easy enough: > > A = ('I:\\VIDS\\Learn Python Track\\07. Regular Expressions in > Python\\Stage ' > '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops', > [], > ['Compiling and Loops.mp4', 'Compiling and Loops.srt']) > >>> A[0] > > ('I:\\VIDS\\Learn Python Track\\07. Regular Expressions in Python\\Stage ' > '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops') > > Still two unconcatenated strings > > And why do I still have tuple parentheses for A[0], which should be a > concatenated string? I'll need to see some actual code (namely, where and how you used os.walk) to have any real idea of what's going on. The online docs for os.walk have a pretty good explanation and example. -- Zach From davea at davea.name Fri Apr 10 01:44:27 2015 From: davea at davea.name (Dave Angel) Date: Thu, 09 Apr 2015 19:44:27 -0400 Subject: [Tutor] annoying directory structure In-Reply-To: References: Message-ID: <55270EDB.2070903@davea.name> On 04/09/2015 06:17 PM, Jim Mooney wrote: Please put your remarks *after* whatever quoting you do, not before. In other words, don't top-post. > Looks like I can work it, but some walk paths are coming out as two strings > back to back, which I know python concatenates with print, but how do I > concatenate them without print so I can use them in my script to append to > the mp4 filenames and have a windows readable path?. i.e., I am getting > this sort of triplet when I go through the generator. After doing that the > rest seems easy enough: > > A = ('I:\\VIDS\\Learn Python Track\\07. Regular Expressions in > Python\\Stage ' > '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops', > [], > ['Compiling and Loops.mp4', 'Compiling and Loops.srt']) > >>> A[0] > > ('I:\\VIDS\\Learn Python Track\\07. Regular Expressions in Python\\Stage ' > '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops') that's not what you'd get if you had done the previous two lines. So please post some real code, and maybe you'll get some help. > > Still two unconcatenated strings You didn't do anything to concatenate anything, so I'm not sure what you're talking about. > > And why do I still have tuple parentheses for A[0], which should be a > concatenated string? > Nonsense without context. What's your code? If you're inside a loop on os.walk, the easiest way to make readable code is to use implicit tuple unpacking. See https://docs.python.org/3.4/library/os.html#os.walk for dirpath, dirnames, filenames = os.walk( whatever ): #Do something here with dirpath and each of the filenames Once you have a path and a basename you need to combine, you *could* use + on the two strings. But it'd be much better to use os.path.join(). See https://docs.python.org/3/library/os.path.html#os.path.join -- DaveA From akleider at sonic.net Fri Apr 10 02:42:19 2015 From: akleider at sonic.net (Alex Kleider) Date: Thu, 09 Apr 2015 17:42:19 -0700 Subject: [Tutor] annoying directory structure In-Reply-To: <55270EDB.2070903@davea.name> References: <55270EDB.2070903@davea.name> Message-ID: On 2015-04-09 16:44, Dave Angel wrote: > for dirpath, dirnames, filenames = os.walk( whatever ): I've always seen it written >>> for dirpath, dirnames, filenames in os.walk( whatever ): Comments?? From zachary.ware+pytut at gmail.com Fri Apr 10 02:45:10 2015 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Thu, 9 Apr 2015 19:45:10 -0500 Subject: [Tutor] annoying directory structure In-Reply-To: References: <55270EDB.2070903@davea.name> Message-ID: On Thu, Apr 9, 2015 at 7:42 PM, Alex Kleider wrote: > On 2015-04-09 16:44, Dave Angel wrote: > > >> for dirpath, dirnames, filenames = os.walk( whatever ): > > > I've always seen it written >>>> >>>> for dirpath, dirnames, filenames in os.walk( whatever ): > > > Comments?? Typo on Dave's part, I'm quite certain he meant to use 'in', since '=' there is a SyntaxError. -- Zach From davea at davea.name Fri Apr 10 03:48:25 2015 From: davea at davea.name (Dave Angel) Date: Thu, 09 Apr 2015 21:48:25 -0400 Subject: [Tutor] annoying directory structure In-Reply-To: References: <55270EDB.2070903@davea.name> Message-ID: <55272BE9.1030500@davea.name> On 04/09/2015 08:45 PM, Zachary Ware wrote: > On Thu, Apr 9, 2015 at 7:42 PM, Alex Kleider wrote: >> On 2015-04-09 16:44, Dave Angel wrote: >> >> >>> for dirpath, dirnames, filenames = os.walk( whatever ): >> >> >> I've always seen it written >>>>> >>>>> for dirpath, dirnames, filenames in os.walk( whatever ): >> >> >> Comments?? > > Typo on Dave's part, I'm quite certain he meant to use 'in', since '=' > there is a SyntaxError. > Quite right. I should have copy/pasted it from the first example following the os.walk tag on the webpage I showed. In fact, I think I did paste the first 3 tokens from the tuple description earlier on that link, and trusted my fingers to do the rest. Sorry for the typo, but not for the advice. -- DaveA From cybervigilante at gmail.com Fri Apr 10 05:07:33 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 9 Apr 2015 20:07:33 -0700 Subject: [Tutor] Tutor Digest, Vol 134, Issue 27 - Re: annoying directory structure (Zachary Ware) Message-ID: > > I'll need to see some actual code (namely, where and how you used > os.walk) to have any real idea of what's going on. The online docs for > os.walk have a pretty good explanation and example. Zach This worked. I didn't know why I got doubled strings, but print concatenated them so I printed to a file, and the text lines all open an mp4 in windows explorer, as expected. Unfortunately they aren't in order, so I guess I'll have to actually read up on walk. I just wanted to knock it out quickly by figuring out the walk output format, and get on with the course ;') tutfiles = open('tutfiles.txt', 'w') p = os.walk('I:\\VIDS\\Learn Python Track\\') for triplet in p: if triplet[2] == []: continue else: if 'mp4' in triplet[2][0]: print(triplet[0] + '\\' + triplet[2][0], file=tutfiles) tutfiles.close() Here are the out of order textlines, going from Track\08 to Track\01 I:\VIDS\Learn Python Track\08. Using Databases in Python\Stage 1\01. Meet Peewee\01. Meet Peewee, Our ORM\Meet Peewee, Our ORM.mp4 I:\VIDS\Learn Python Track\01. Python Basics\Python Basics\Stage 6\06. Pick a Number! Any Number!\02. The Solution\The Solution.mp4 Here is what I meant by doubled strings. The tuples output by walk had two strings in a row as element zero, Prior to the first comma, with element 1 being an empty list, so I couldn't figure how to concatenate the two strings directly, without print, to use in my file listing. (*'I:\\VIDS\\Learn Python Track\\07. Regular Expressions in Python\\Stage ' '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops'*, [], ['Compiling and Loops.mp4', 'Compiling and Loops.srt']) Jim From kale at kalegood.com Fri Apr 10 02:39:11 2015 From: kale at kalegood.com (Kale Good) Date: Thu, 09 Apr 2015 20:39:11 -0400 Subject: [Tutor] Execute on 200 line segments of CSV Message-ID: <55271BAF.3080105@kalegood.com> Hello, Python newbie here; I'm trying to figure out how to get python to execute code on 200-line chunks of a 5000 line CSV. I haven't a clue where to start on this. So the code would execute on lines 1-200, 201-400, etc. Thanks, Kale -- ------------------------------------------------------------------------ Kale Good: Guitar Instructor ? phillyguitarlessons.com phone: (215)260-5383 * 4705 Baltimore Ave, Phila, PA 19143 :Mailing & Lessons * 1867 Frankford Ave. Phila, PA 19125 :Lessons Google+ Facebook Read my article "The Seven Secrets to Six String Success " at GuitarNoise.com Leading the Journey from No-Skills-Guitarist to Talented Musician! From __peter__ at web.de Fri Apr 10 09:57:25 2015 From: __peter__ at web.de (Peter Otten) Date: Fri, 10 Apr 2015 09:57:25 +0200 Subject: [Tutor] Execute on 200 line segments of CSV References: <55271BAF.3080105@kalegood.com> Message-ID: Kale Good wrote: > Python newbie here; I'm trying to figure out how to get python to > execute code on 200-line chunks of a 5000 line CSV. I haven't a clue > where to start on this. So the code would execute on lines 1-200, > 201-400, etc. Use the csv module https://docs.python.org/3.4/library/csv.html to read the rows from the CSV. Iterate over the rows with a for loop and collect the rows in a list (let's call it 'chunk'). Check the chunk list's length on every iteration of the for loop. When the list's length is 200 do what you want with those 200 rows, then replace the list with a new empty list. When the for loop ends there may be lines remaining in the chunk list, e. g. when the CSV file has 5100 lines there will be a final chunk containing 100 rows that is not handled by the code in the for loop. It's up you to detect it and to decide what to do with this smaller chunk. Come back when you have some code that we can help fix or improve. From davea at davea.name Fri Apr 10 13:39:44 2015 From: davea at davea.name (Dave Angel) Date: Fri, 10 Apr 2015 07:39:44 -0400 Subject: [Tutor] Tutor Digest, Vol 134, Issue 27 - Re: annoying directory structure (Zachary Ware) In-Reply-To: References: Message-ID: <5527B680.5090604@davea.name> Please at least fix the subject line. Thanks for deleting the irrelevant parts of the digest, but you're pretending to continue a thread, while having a bogus subject, and sending a message that's not at all linked to the previous part of the thread. When I used to use a digest, I was able to open a particular message within the digest (I think the individual messages were considered attachments, and I just double-clicked on one such attachment). Then i could reply, and it actually worked. Your mileage may vary, which is why it's better to just skip digests when you're actually participating. On 04/09/2015 11:07 PM, Jim Mooney wrote: >> >> I'll need to see some actual code (namely, where and how you used >> os.walk) to have any real idea of what's going on. The online docs for >> os.walk have a pretty good explanation and example. > > > Zach > > This worked. I didn't know why I got doubled strings, but print > concatenated them so I printed to a file, and the text lines all open an > mp4 in windows explorer, as expected. Unfortunately they aren't in order, > so I guess I'll have to actually read up on walk. I just wanted to knock it > out quickly by figuring out the walk output format, and get on with the > course ;') > > tutfiles = open('tutfiles.txt', 'w') > p = os.walk('I:\\VIDS\\Learn Python Track\\') > for triplet in p: > if triplet[2] == []: > continue > else: > if 'mp4' in triplet[2][0]: If you're looking for an extension of mp4, you should either use endswith, or use os.path.splitext to get the actual extension. The way you have it now, you'll also tag a file that happens to have those 3 letters somewhere in the middle. The other thing weird in this code is you're only looking at the first file in the directory. If the file you're interested in happens to be the fifth, you'll never see it. Normally, you need to loop over triplet[2] > print(triplet[0] + '\\' + triplet[2][0], file=tutfiles) > > tutfiles.close() > > Here are the out of order textlines, going from Track\08 to Track\01 If you want the directory names to be sorted, and your OS doesn't happen to sort them, you must do it yourself. Simply sort triplet[1] each time. If you also want the filenames within a directory to be sorted, then sort them as well. These two sorts would take place just before your "if triple3t[2]" above. > > I:\VIDS\Learn Python Track\08. Using Databases in Python\Stage 1\01. Meet > Peewee\01. Meet Peewee, Our ORM\Meet Peewee, Our ORM.mp4 > I:\VIDS\Learn Python Track\01. Python Basics\Python Basics\Stage 6\06. > Pick a Number! Any Number!\02. The Solution\The Solution.mp4 > > Here is what I meant by doubled strings. The tuples output by walk had two > strings in a row as element zero, Prior to the first comma, with element 1 > being an empty list, so I couldn't figure how to concatenate the two > strings directly, without print, to use in my file listing. No idea what this paragraph is trying to say. But the first element of the tuple is a string, so it cannot have two items in it. If it seems to, perhaps you have some unusual filenames, like the asterisk and parenthesis in the following thingie. > > (*'I:\\VIDS\\Learn Python Track\\07. Regular Expressions in Python\\Stage ' > '1\\01. Introduction to Regular Expressions\\07. Compiling and Loops'*, [], > ['Compiling and Loops.mp4', 'Compiling and Loops.srt']) > If we're going to make any sense of that mess, you need to show the code that produced it. -- DaveA From dyoo at hashcollision.org Fri Apr 10 20:46:32 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Fri, 10 Apr 2015 11:46:32 -0700 Subject: [Tutor] Execute on 200 line segments of CSV In-Reply-To: References: <55271BAF.3080105@kalegood.com> Message-ID: >> Python newbie here; I'm trying to figure out how to get python to >> execute code on 200-line chunks of a 5000 line CSV. I haven't a clue >> where to start on this. So the code would execute on lines 1-200, >> 201-400, etc. Peter's suggestion to reuse the csv library is appropriate: you want to reuse the csv parser that's available in the standard library. This will give you an "iterable", an object that we can use to march down each row of the file, using the technique that Peter describes. --- The following is for intermediate programmers. The "chunking" logic can be split off from the processing of those chunks, if we take advantage of Python's generators. Something like this: ################################## def chunk(iterable, chunkSize): """Takes an iterable, and "chunks" it into blocks.""" currentChunk = [] for item in iterable: currentChunk.append(item) if len(currentChunk) >= chunkSize: yield(currentChunk) currentChunk = [] if len(currentChunk) > 0: yield(currentChunk) ################################## If we have a utility like this, then we can write a natural loop on the chunks, such as: ################################################################### >>> blocks = chunk('thisisatestoftheemergencybroadcastsystem', 5) >>> for b in blocks: ... print b ... ['t', 'h', 'i', 's', 'i'] ['s', 'a', 't', 'e', 's'] ['t', 'o', 'f', 't', 'h'] ['e', 'e', 'm', 'e', 'r'] ['g', 'e', 'n', 'c', 'y'] ['b', 'r', 'o', 'a', 'd'] ['c', 'a', 's', 't', 's'] ['y', 's', 't', 'e', 'm'] ################################################################### Splitting of the chunking logic like this should allow us to separate one concern, the chunking, from the primary concern, the processing of each chunk. From zachary.ware+pytut at gmail.com Sat Apr 11 02:14:16 2015 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Fri, 10 Apr 2015 19:14:16 -0500 Subject: [Tutor] annoying directory structure Message-ID: On Thu, Apr 9, 2015 at 10:07 PM, Jim Mooney wrote: [Previously, I wrote:] >> I'll need to see some actual code (namely, where and how you used >> os.walk) to have any real idea of what's going on. The online docs for >> os.walk have a pretty good explanation and example. > > > This worked. I didn't know why I got doubled strings, but print > concatenated them so I printed to a file, and the text lines all open an > mp4 in windows explorer, as expected. Unfortunately they aren't in order, > so I guess I'll have to actually read up on walk. I just wanted to knock it > out quickly by figuring out the walk output format, and get on with the > course ;') > > tutfiles = open('tutfiles.txt', 'w') > p = os.walk('I:\\VIDS\\Learn Python Track\\') > for triplet in p: > if triplet[2] == []: > continue > else: > if 'mp4' in triplet[2][0]: > print(triplet[0] + '\\' + triplet[2][0], file=tutfiles) > > tutfiles.close() Frankly, that's a bit horrifying :). I'm glad you came up with a solution that works for you using the tools available to you, but it's far from idiomatic Python code. Here's how I would write it (please excuse any syntax errors; I'm not testing it. Logic errors, I'll take the blame :) ). """ import os def get_filenames(top_level_dir): all_video_files = [] for dir, dirs, files in os.walk(os.path.abspath(top_level_dir)): for filename in files: if filename.endswith('.mp4'): all_files.append(os.path.join(dir, filename)) return all_video_files print(*get_filenames("your root directory"), sep='\n') """ If you need them sorted in some particular way, you can sort the list before printing it, using the sort() method of the list (and probably the 'key' keyword argument). Please take a look at this and try to understand what it's doing, and ask about anything that doesn't make sense (that's the most important part!). Hope this helps, -- Zach From vick1975 at orange.mu Sat Apr 11 14:32:38 2015 From: vick1975 at orange.mu (Vick) Date: Sat, 11 Apr 2015 16:32:38 +0400 Subject: [Tutor] Hi Message-ID: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> Hello I've been using Python 27 on Windows for as long as I have used a computer for intelligent purposes, viz. since 2000 I think, well the earlier versions till the current version I'm using now. I used it primarily for mathematical precision on numerical computations. I make my own codes. I'm fluent in it and in VBA. I also use Mathematica (Home Edition) to compare. However as Mathematica is largely symbolic, I prefer Python. However I recently talked to a guy online and he told me the following, which actually intrigued and surprised me: "The vast majority of numerical codes in science, including positional astronomy, are written in Fortran and C/C++. If you wish to use these codes in minority and less efficient languages such as Python and VBA, learning to translate this code into those languages is a skill you will have to acquire." The "codes" in question are referring to a query I posed to him regarding the GUST86 theory on the computational position of Uranus' natural satellites authored by Laskar and Jacobson in 1987. The "code" is readily downloadable in Fortran at the IMCCE ftp site. But his statement is insinuating that Python is inferior to Fortran as a mathematical tool and that all of the scientific community prefers to use Fortran. My question is simple: Is he right or wrong? Thanks Vick From steve at pearwood.info Sat Apr 11 15:41:13 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 11 Apr 2015 23:41:13 +1000 Subject: [Tutor] Hi In-Reply-To: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> Message-ID: <20150411134112.GH5760@ando.pearwood.info> Hi Vick, and welcome! My replies to your questions are below, interleaved with your comments. On Sat, Apr 11, 2015 at 04:32:38PM +0400, Vick wrote: > However I recently talked to a guy online and he told me the following, > which actually intrigued and surprised me: > > "The vast majority of numerical codes in science, including positional > astronomy, are written in Fortran and C/C++. If you wish to use these codes > in minority and less efficient languages such as Python and VBA, learning to > translate this code into those languages is a skill you will have to > acquire." [...] > But his statement is insinuating that Python is inferior to Fortran as a > mathematical tool and that all of the scientific community prefers to use > Fortran. > > My question is simple: Is he right or wrong? He is partly right, partly wrong. But mostly wrong. Twenty years ago, if you wanted to do scientific computing, C and Fortran were essential. They are still very important, but they are no longer essential. There are many professional-quality mathematical libraries. Older libraries are nearly all written in C/C++ or Fortran. Some are older libraries are written in Pascal, but because few people use Pascal any more, you won't find many of them still in use. Some newer libraries are written in Java. In the future, I would expect new scientific libraries to start coming out written in Julia: http://julialang.org/ Although these libraries are written in C or Fortran, you don't need to program in those two languages to *use* those libraries. Most scripting languages like Python, Lua or Ruby include ways to call code in C or Fortran libraries as if they were written in Python (or Lua, Ruby, and so forth). We call languages like Python a "glue language", because it is very good for "gluing together" code from different libraries. You want to use this library for planetary orbit calculations, written in Fortran, and that library for calculating lunar eclipses written in C, so you use a Python script to bring them together. Many mathematicians, statisticians and scientists use products such as Mathematica, Matlab, R, SAS, Minitab, Maple, and similar. These are all good products that have been around for a long time, with their own strengths and weaknesses. One Python-based product which is becoming widely used in scientific circles is Numpy, together with its sister-library Scipy. The core numeric routines in Numpy and Scipy are mostly written in C and Fortran, but the interface is designed for use with Python. http://www.numpy.org/ http://www.scipy.org/ Another Python product is SAGE, which aims to be a free alternative to Maple, Mathematica and other similar products. http://www.sagemath.org/ The idea is to create a group of powerful maths, statistics and scientific libraries. Those libraries can use whatever language they want, and often they are written in C and Fortran, but the glue that holds them together is Python. Together, they combine the power of low-level, hard-to-use but powerful fast languages like Fortran and C with the ease of use and convenience of modern high-level languages like Python. The core of scientific computing with Python includes: Numpy - fast N-dimensional array calculations Scipy - scientific computing libraries Matplotlib - 2D graphing IPython - enhanced interactive console with Mathematica-like notebook Sympy - symbolic mathematics Pandas - data analysis SAGE - integrated scientific computing system Parts of these are written in Python, and parts in C, Fortran, Javascript, and potentially any language imaginable. I also expect that people can start using PyPy to run pure-Python code almost as fast as C: http://pypy.org/ Or they can use Cython to write C code using Python syntax: http://cython.org/ ? All of these are parts of the Python ecosystem, and are why Python is currently becoming the "go-to" language for scientific computing. Where scientists used to write code in Fortran (hard and slow to write, but fast to run) or expensive proprietary products like Mathematica or Matlab, many people are gradually moving towards the Python ecosystem of Python, Numpy, IPython notebooks, and others. This post explains Python's advantages over Matlab, why the author thinks that scientific computing will continue to move towards Python, and links to a number of other good articles from people who already have done so. http://cyrille.rossant.net/why-using-python-for-scientific-computing/ My advice if you want to be a good scientific programmer: - Stay with Python. Anyone who tries to tell you that you need to know how to program in Fortran or C to do scientific computing is wrong. - Learn how to program in Python as well as possible. - Learn when *not* to program in Python, and know when to use existing tools already written in C, Fortran or other languages. Chances are very good that Numpy, Scipy and others above already solve some of your problems. - If you really need high-speed computing power that Python alone cannot provide, consider PyPy, Cython or Numba first. If and only if they still don't provide what you need should you bother learning C or Fortran and using those. -- Steve From wrw at mac.com Sat Apr 11 15:39:43 2015 From: wrw at mac.com (William Ray Wing) Date: Sat, 11 Apr 2015 09:39:43 -0400 Subject: [Tutor] Hi In-Reply-To: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> Message-ID: > On Apr 11, 2015, at 8:32 AM, Vick wrote: > [byte] > However I recently talked to a guy online and he told me the following, > which actually intrigued and surprised me: > > "The vast majority of numerical codes in science, including positional > astronomy, are written in Fortran and C/C++. If you wish to use these codes > in minority and less efficient languages such as Python and VBA, learning to > translate this code into those languages is a skill you will have to > acquire." > > The "codes" in question are referring to a query I posed to him regarding > the GUST86 theory on the computational position of Uranus' natural > satellites authored by Laskar and Jacobson in 1987. The "code" is readily > downloadable in Fortran at the IMCCE ftp site. > > But his statement is insinuating that Python is inferior to Fortran as a > mathematical tool and that all of the scientific community prefers to use > Fortran. > > My question is simple: Is he right or wrong? > > He is probably right, but only because most large scientific codes have historical roots that date back to the days when FORTRAN was the only language readily available on the computers scientists used. Even today, FORTRAN compilers can frequently optimize typical scientific code to tighter (faster) executable code than the compilers for other, more modern, richer languages. HOWEVER, that said, more and more scientific code is being written with Python as the organizing language which calls mathematical libraries written in FORTRAN. Libraries like numpy make heavy use of FORTRAN arrays, while allowing the scientific programmer to concentrate on the higher levels of the science being modeled. Bill > > Thanks > > Vick > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From martin at linux-ip.net Sat Apr 11 17:05:37 2015 From: martin at linux-ip.net (Martin A. Brown) Date: Sat, 11 Apr 2015 08:05:37 -0700 Subject: [Tutor] Hi In-Reply-To: <20150411134112.GH5760@ando.pearwood.info> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> <20150411134112.GH5760@ando.pearwood.info> Message-ID: Greetings Steven, Much great advice snipped. Is it possible (using U+1F600 through U+1F64F or otherwise) to offer a standing ovation for such a relevant, thorough, competent and well-written reply? Thank you, as always, -Martin (You know, Steven, we had gotten so accustomed to your slapdash answers, that this one comes as a huge surprise.) -- Martin A. Brown http://linux-ip.net/ From vick1975 at orange.mu Sat Apr 11 18:35:08 2015 From: vick1975 at orange.mu (Vick) Date: Sat, 11 Apr 2015 20:35:08 +0400 Subject: [Tutor] Hi In-Reply-To: References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> Message-ID: <000701d07475$7a833840$6f89a8c0$@orange.mu> Hi, Thanks for replying! I understand as you said that since it was the very first language available to them therefore scientists at large got stuck with it as I presume it would have become the primary programming language example given in their textbooks or study materials. However your reply does not answer the first part of the proposition of my question! Given that all scientists like to code in Fortran but does it mean that Python is inferior to it in terms of mathematical / scientific computation? Thanks Vick -----Original Message----- From: William Ray Wing [mailto:wrw at mac.com] Sent: Saturday, 11 April, 2015 17:40 To: Vick Cc: William R. Wing; webmaster at python.org; tutor at python.org Subject: Re: [Tutor] Hi > On Apr 11, 2015, at 8:32 AM, Vick wrote: > [byte] > However I recently talked to a guy online and he told me the > following, which actually intrigued and surprised me: > > "The vast majority of numerical codes in science, including positional > astronomy, are written in Fortran and C/C++. If you wish to use these > codes in minority and less efficient languages such as Python and VBA, > learning to translate this code into those languages is a skill you > will have to acquire." > > The "codes" in question are referring to a query I posed to him > regarding the GUST86 theory on the computational position of Uranus' > natural satellites authored by Laskar and Jacobson in 1987. The "code" > is readily downloadable in Fortran at the IMCCE ftp site. > > But his statement is insinuating that Python is inferior to Fortran as > a mathematical tool and that all of the scientific community prefers > to use Fortran. > > My question is simple: Is he right or wrong? > > He is probably right, but only because most large scientific codes have historical roots that date back to the days when FORTRAN was the only language readily available on the computers scientists used. Even today, FORTRAN compilers can frequently optimize typical scientific code to tighter (faster) executable code than the compilers for other, more modern, richer languages. HOWEVER, that said, more and more scientific code is being written with Python as the organizing language which calls mathematical libraries written in FORTRAN. Libraries like numpy make heavy use of FORTRAN arrays, while allowing the scientific programmer to concentrate on the higher levels of the science being modeled. Bill > > Thanks > > Vick > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From steve at pearwood.info Sat Apr 11 19:12:17 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 12 Apr 2015 03:12:17 +1000 Subject: [Tutor] Hi In-Reply-To: <000701d07475$7a833840$6f89a8c0$@orange.mu> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> <000701d07475$7a833840$6f89a8c0$@orange.mu> Message-ID: <20150411171216.GK5760@ando.pearwood.info> On Sat, Apr 11, 2015 at 08:35:08PM +0400, Vick wrote: > Given that all scientists like to code in Fortran but does it mean that > Python is inferior to it in terms of mathematical / scientific computation? Scientists do not like to code in Fortran. Anybody who tells you that is mistaken. If they wanted to be programmers, they would have become programmers, not scientists. If they *have* to program, they will, but they would rather do science, not programming. No, Python is not inferior. It is just different. It is designed to have different strengths and weaknesses compared to Fortran. Strengths of Fortran: - You can write very fast, powerful numeric programs. - Fortran excels at high-speed number-crunching. - Fortran is an old language, in fact it is the first (and therefore oldest) programming language. Because it has been around since the 1950s, there are lots of Fortran libraries you can use -- if you can find them, or afford them. Weaknesses of Fortran: - It is difficult to write Fortran code. - It is an old language which lacks modern programming features. - It is hard to work with strings or do anything except number-crunching. - It is a very low-level language, which means you have to care about things that have nothing to do with the problem you are trying to solve, like memory. Strengths of Python: - It is a modern language with many modern features that Fortran lacks. - It is easy to work with strings and other associated data structures. - It is a high-level language that automatically looks after all the boring book-keeping details, like memory. - It excels at rapid application development. - It excels at being a glue-language for calling pre-written C or Fortran libraries. Weaknesses: - Pure Python code may be a bit slower that C or Fortran code. (But that doesn't matter, if you can call a C or Fortran library to do the heavy lifting, and leave Python to do the parts that C or Fortran struggle with.) When people tell you that "real scientists" write their code in Fortran, they are being macho pretentious fools. Do "real scientists" also make their own test tubes from sand they dug out of the ground themselves? No, of course not. It isn't 1800 any more, and the average scientist no more needs to program in Fortran than they need to grind their own lenses. Some scientists may still need to use Fortran, but that is a sign that they are still stuck with using ancient computer programs, not a good thing to be copied. To give an analogy, Fortran is like flying a Suyez rocket. It is very difficult to learn to fly, but once you master it you can go into space in seconds. But it will takes years of training and months of preparation for each flight. Python is like driving a car: it won't get you into space, but it takes weeks to learn to drive a car, not years, and you can jump in the car and drive to the shops with no preparation needed. And you can get in your car and drive to the Suyez rocket, but you cannot get in the Suyez and fly to where you parked your car. Which is better? Well, it depends. If you want to drive to the shops, the Suyez is completely useless. It costs fifty million dollars every time you use it, and you cannot even get to the shops. If you want to spend six months writing a Fortran program to analysis your data, you can, and when you have finished, it will run in five seconds. Or you can spend six days writing it in Python, and it will run in five minutes. Which is better? To be more precise: Python can use Fortran and C libraries to do the heavy lifting, the difficult work. Doing that from Fortran or C is a horrible experience: they are hard languages to learn, and hard to use. But using those libraries from Python is fast, and fun, and easy, and that means that scientists can spend more time doing science and less time trying to program the computer. -- Steve From alan.gauld at btinternet.com Sat Apr 11 20:00:23 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 11 Apr 2015 19:00:23 +0100 Subject: [Tutor] Hi In-Reply-To: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> Message-ID: On 11/04/15 13:32, Vick wrote: > "The vast majority of numerical codes in science, including positional > astronomy, are written in Fortran and C/C++. True, because the vast majorioty of "scientific codes" (ie libraries) were written many years ago and are still maintained in the languages used back then. Mainly that was Fortran for science. The vast majpority of *new* scientific code being written is not in Fortran (and not much in C either). In fact I don't know of any local university that still teaches Fortran as part of their normal science or math syllabus. Most new scientific work is done in Mathematica or similar high level language and then translated when needed into a lower level language like C or increasingly Java. (And if its statistics often into R.) > If you wish to use these codes in minority and less efficient > languages such as Python and VBA, Minority - False. There are certainly more VBA programmers than Fortan ones. And probably as many as there are C/C++ Python is only a little way behind Fortan if at all. But if we limit ourselves to the scientific community then its closer to being true. > learning to translatethis code into those languages > is a skill you will have to acquire." Completely false. Almost all modern scripting languages have mechanisms to call C libraries easily. (And high quality Fortran to C translators exist.) Only if you need to write very high performance routines that do not already exist - ie you are a research scientist or mathematician - do you need to learn C or Fortran. And even then its unlikely to be your first choice. > The "codes" in question are referring to a query I posed to him regarding > the GUST86 theory on the computational position of Uranus' natural > satellites authored by Laskar and Jacobson in 1987. The "code" is readily > downloadable in Fortran at the IMCCE ftp site. Have you investigated the SciPy libraries, and especially the SciKit collection of specialist libraries. There are several astro libraries in there. Most are written in C but wrapped for use from Python. > But his statement is insinuating that Python is inferior to Fortran as a > mathematical tool No, he quite correctly states that Python is less efficient than C or Fortran for numerical analysis. That is true of mainstream, Python. There are various projects attempting to address that shortfall. But there are many dimensions to the "goodness" of a programming language and "efficiency" (ie runtime speed) is only one of them. And on modern computing hardware it is rarely the most important one. Others include development speed (programming efficiency), portability, reliability, connectivity, abstraction capability, readability/maintainability, tool support etc. To say any language is "inferior" to another needs to be qualified by the dimension(s) being measured. I see Steven has just posted a similar mail that goes into the comparisons in more detail. So I'll stop here :-) > and that all of the scientific community prefers to use > Fortran. That depends who you talk to. I know many scientists who swear by Mathematica and Matlab and don't use anything else. > My question is simple: Is he right or wrong? The answer is less simple: it depends... Finally, for a more light-hearted take on the topic, see: http://www.ee.ryerson.ca/~elf/hack/realmen.html For maximum offence substitute Python for Pascal ;-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cybervigilante at gmail.com Sat Apr 11 19:41:28 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 11 Apr 2015 10:41:28 -0700 Subject: [Tutor] list semantics Message-ID: Why does the first range convert to a list, but not the second? >>> p = list(range(1,20)), (range(40,59)) >>> p ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], range(40, 59)) -- Jim "Stop, Harold! That bagel has radishes!" "Thank God, Mary - you've saved me again!" From lac at openend.se Sat Apr 11 18:56:32 2015 From: lac at openend.se (Laura Creighton) Date: Sat, 11 Apr 2015 18:56:32 +0200 Subject: [Tutor] On learning Fortran and C++ for scientific computing In-Reply-To: Message from William Ray Wing of "Sat, 11 Apr 2015 09:39:43 -0400." References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> Message-ID: <201504111656.t3BGuWlD028763@fido.openend.se> These days, most important scientific libraries are wrapped so that you call call them directly from python. Google for "python bindings " and see if you get any hits. If you have a library that doesn't have python bindings, you can probably make them. Start reading here: http://intermediate-and-advanced-software-carpentry.readthedocs.org/en/latest/c++-wrapping.html http://scicomp.stackexchange.com/questions/2283/which-package-should-i-use-to-wrap-modern-fortran-code-with-python to see about wrapping C++ and Fortran code. But chances are somebody has already done it. And for astronomical calculations, I just use pyephem. http://rhodesmill.org/pyephem/index.html It is difficult, and usually pointless to argue with somebody who prefers to use Fortran or C++ about using some other language. People like what they are used to. Moreover, in the case of Fortran and C++, these languages are significantly harder to use than Python, where harder, in this case, means -- the code you write is more prone to errors. Also, it is very easy to write inefficient programs in C++ or Fortran, and scientists, who are not professional programmers are extremely prone to doing this. So while a Fortran or C++ library may be fast (if the library author knew what he or she was doing, or the community has fixed inefficiencies over the years) that doesn't mean that your own C++ or Fortran code is guaranteed to be fast. And, of course, if it takes you 5 times as long in your personal time to write the code, do you actually care how fast the result runs? For very long running calculations, where time is money, the answer may be yes. But if all you want to know is where Uranus is going to be next Thursday so you can point your telescope at it, not a bit. If you need something that runs faster than the standard version of python, you may be able to get it with numpy and the other scientific tools here: http://www.scipy.org/ or with pypy http://speed.pypy.org/ . The number of problems where you can legitimately claim that you badly need the speed that C++ and Fortran provide is shrinking all the time, as machines grow faster. Plus, in modern computing the new challenge is to use multiple cores. It's a very hard problem, and all the old C++ and Fortran libraries were created with the assumption that there is only one core. Right now we don't actually know how to use multiple cores efficiently -- it is hot research in computer science right now, with no particularly good answers. But once we figure out how to do this, all the old C++ and Fortran libraries are probably going to have to be rewritten with this in mind. (A solution that doesn't require such re-writing would, of course be highly desirable, but things are not looking very good on that front.) If your real question is 'would it be desirable to learn C++ and Fortran from a historical perspective, to get an understanding of how important computational libraries in my field are structured', then I am the wrong person to ask. I knew both of these languages before there was a Python. I think learning these langauges will indeed make understanding the old libraries easier, but _using_ these languages to do real work isn't needed. Or rather, if you are one of the people who needs to use them, then you would already know that you are, and why, and wouldn't be asking the question. The world is full of things to learn, so you need to do your own prioritisation of Fortran vs everything else you haven't learned yet. :) Best of luck, Laura Creighton p.s. I gave this topic a more descriptive subject line than 'Hi' but it should still thread with the original. From joel.goldstick at gmail.com Sat Apr 11 20:15:49 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Sat, 11 Apr 2015 14:15:49 -0400 Subject: [Tutor] list semantics In-Reply-To: References: Message-ID: On Sat, Apr 11, 2015 at 1:41 PM, Jim Mooney wrote: > Why does the first range convert to a list, but not the second? > >>>> p = list(range(1,20)), (range(40,59)) >>>> p > ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], > range(40, 59)) > Assuming you are using python 3.x range is a generator, so it only produces values if you iterate over it > -- > Jim > > "Stop, Harold! That bagel has radishes!" > "Thank God, Mary - you've saved me again!" > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From timomlists at gmail.com Sat Apr 11 20:17:10 2015 From: timomlists at gmail.com (Timo) Date: Sat, 11 Apr 2015 20:17:10 +0200 Subject: [Tutor] list semantics In-Reply-To: References: Message-ID: <55296526.2040101@gmail.com> Op 11-04-15 om 19:41 schreef Jim Mooney: > Why does the first range convert to a list, but not the second? > >>>> p = list(range(1,20)), (range(40,59)) >>>> p > ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], > range(40, 59)) > I'm not sure I understand correctly. This is what the top of help(range) says: < Help on class range in module builtins: class range(object) | range(stop) -> range object | range(start, stop[, step]) -> range object | | Return a virtual sequence of numbers from start to stop by step. > So range() returns a range object. In your example you convert the first one to a list with list(), but not the second, so it prints the range object. >>> range(2) range(0, 2) >>> list(range(2)) [0, 1] Timo From steve at pearwood.info Sat Apr 11 21:02:58 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 12 Apr 2015 05:02:58 +1000 Subject: [Tutor] list semantics In-Reply-To: References: Message-ID: <20150411190257.GL5760@ando.pearwood.info> On Sat, Apr 11, 2015 at 10:41:28AM -0700, Jim Mooney wrote: > Why does the first range convert to a list, but not the second? > > >>> p = list(range(1,20)), (range(40,59)) > >>> p > ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], > range(40, 59)) Why would the second convert to a list? You don't call list() on it. You create a tuple, p, with two items. The first item is: list(range(1, 20)) and the second item is: range(40, 59) so you end up with p being a tuple ([1, 2, 3, ..., 19], range(40, 59)). The fact that you surround the second item with round brackets (parentheses) means nothing -- they just group the range object on its own. A bit like saying 1 + (2), which still evaluates as 3. -- Steve From steve at pearwood.info Sat Apr 11 21:09:43 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 12 Apr 2015 05:09:43 +1000 Subject: [Tutor] list semantics In-Reply-To: References: Message-ID: <20150411190942.GM5760@ando.pearwood.info> On Sat, Apr 11, 2015 at 02:15:49PM -0400, Joel Goldstick wrote: > On Sat, Apr 11, 2015 at 1:41 PM, Jim Mooney wrote: > > Why does the first range convert to a list, but not the second? > > > >>>> p = list(range(1,20)), (range(40,59)) > >>>> p > > ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], > > range(40, 59)) > > > Assuming you are using python 3.x range is a generator, so it only > produces values if you iterate over it Almost correct, but not quite. range, like xrange in Python 2, is not a generator, but a custom-made lazy sequence object. py> gen() # This actually is a generator. py> range(1, 10) # This is not. range(1, 10) Range objects are special: not only do they produce values lazily as needed, but they also support len(), indexing, slicing, and membership testing, none of which generators are capable of doing: py> r = range(1, 30, 3) py> len(r) 10 py> r[8] # indexing 25 py> r[2:5] # slicing range(7, 16, 3) py> 9 in r # membership testing False py> 10 in r True All those results are calculated lazily, without having to pre-calculate a potentially enormous list. -- Steve From breamoreboy at yahoo.co.uk Sat Apr 11 21:20:14 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Sat, 11 Apr 2015 20:20:14 +0100 Subject: [Tutor] list semantics In-Reply-To: <20150411190257.GL5760@ando.pearwood.info> References: <20150411190257.GL5760@ando.pearwood.info> Message-ID: On 11/04/2015 20:02, Steven D'Aprano wrote: > On Sat, Apr 11, 2015 at 10:41:28AM -0700, Jim Mooney wrote: >> Why does the first range convert to a list, but not the second? >> >>>>> p = list(range(1,20)), (range(40,59)) >>>>> p >> ([1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18, 19], >> range(40, 59)) > > Why would the second convert to a list? You don't call list() on it. > > You create a tuple, p, with two items. The first item is: > > list(range(1, 20)) > > and the second item is: > > range(40, 59) > > so you end up with p being a tuple ([1, 2, 3, ..., 19], range(40, 59)). > > The fact that you surround the second item with round brackets > (parentheses) means nothing -- they just group the range object on its > own. A bit like saying 1 + (2), which still evaluates as 3. > To follow up the tuple is created with a comma *NOT* parenthesis. So in the example it is the second comma, the one immediately after the call to list(), that makes p a tuple. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From steve at pearwood.info Sat Apr 11 21:21:53 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 12 Apr 2015 05:21:53 +1000 Subject: [Tutor] list semantics In-Reply-To: <20150411190942.GM5760@ando.pearwood.info> References: <20150411190942.GM5760@ando.pearwood.info> Message-ID: <20150411192153.GN5760@ando.pearwood.info> On Sun, Apr 12, 2015 at 05:09:43AM +1000, Steven D'Aprano wrote: > Almost correct, but not quite. range, like xrange in Python 2, is not a > generator, but a custom-made lazy sequence object. > > py> gen() # This actually is a generator. > > py> range(1, 10) # This is not. > range(1, 10) Oops, I forgot to show where gen() came from. Sorry about that, just a cut-and-paste error. py> def gen(): ... yield 1 ... py> gen() # This actually is a generator. -- Steve From joel.goldstick at gmail.com Sat Apr 11 22:53:43 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Sat, 11 Apr 2015 16:53:43 -0400 Subject: [Tutor] list semantics In-Reply-To: <20150411192153.GN5760@ando.pearwood.info> References: <20150411190942.GM5760@ando.pearwood.info> <20150411192153.GN5760@ando.pearwood.info> Message-ID: On Sat, Apr 11, 2015 at 3:21 PM, Steven D'Aprano wrote: > On Sun, Apr 12, 2015 at 05:09:43AM +1000, Steven D'Aprano wrote: > >> Almost correct, but not quite. range, like xrange in Python 2, is not a >> generator, but a custom-made lazy sequence object. >> >> py> gen() # This actually is a generator. >> >> py> range(1, 10) # This is not. >> range(1, 10) > > Oops, I forgot to show where gen() came from. Sorry about that, just a > cut-and-paste error. > > py> def gen(): > ... yield 1 > ... > py> gen() # This actually is a generator. > > Thanks for the tip Steve > > > -- > Steve > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From omohundr at hawaii.edu Sun Apr 12 01:15:53 2015 From: omohundr at hawaii.edu (Michael Omohundro) Date: Sat, 11 Apr 2015 13:15:53 -1000 Subject: [Tutor] Changing spatial reference of shapefiles in folder and exporting to new folder Message-ID: I want to assemble a script to: 1) input a folder with shapefiles with different coordinate systems, 2) allow the user through a toolbox script to choose a desired coordinate system, and then 3) export all the shapefiles with the new coordinate system to a new folder. So the problem is I don't know how to get the user to choose the coordinate system they want when I create the script in toolbox. Here is my code: import arcpy arcpy.env.workspace = arcpy.GetParameterAsText(0) fcList = arcpy.ListFeatureClasses() try: inFolder = arcpy.ListFeatureClasses() template = arcpy.GetParameteAsText(1) outFolder = arcpy.GetParameterAsText(2) arcpy.AddMessage(template) srf = arcpy.Describe(template).spatialReference.name for fc in fcList: if srf.Name == "Unknown": # skip continue else: arcpy.Describe(fc).spatialReference.name != srf.name: arcpy.Project_management (fc, outFolder + "\\" + fc, desc, {transform_method}, {in_coor_system}) # I have attached the window I am making in the toolbox to this email. I also get this error when I run the script in the toolbox: SyntaxError: invalid syntax (Final_Proj_DRAFT.py, line 16)Failed to execute (SpatRefAutomation). Line 16 of the code reads: spatialRef = arcpy.Describe(inputFolder).spatialReference Please help me. From dyoo at hashcollision.org Sun Apr 12 01:50:07 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Sat, 11 Apr 2015 16:50:07 -0700 Subject: [Tutor] Changing spatial reference of shapefiles in folder and exporting to new folder In-Reply-To: References: Message-ID: Hi Michael, Your question appears to be specifically about the ArcGIS library. Unfortunately, I would assume very few of us have expertise on this particular third-party mapping library; we're mostly a forum for teaching basic Python programming. We can help on non-domain-specific Python-learning issues, but for anything that's specific to ArcGIS, you'll probably have more success talking to the ArcGIS folks. I believe you can find the ArcGIS folks at: https://geonet.esri.com/community/developers/gis-developers/python With that in mind: I will take a look at your program from a neutral standpoint, assuming no domain-specific knowledge: 1. Your program is malformed because it has a "try" block, but with no "except" or "finally". This is a syntax error. The program is not perfectly formed, so Python will not run your program until it has the form of a correct program. (Whether it does what you want is an entirely different, "semantic" matter.) When you're using 'try', your program is grammatically prompting the setting up of an exception handler. ################################## try: inFolder = arcpy.ListFeatureClasses() ... ################################## ... But your program has omitted what should happen if an exception does occur! What should happen if things go wrong? Since that hasn't been written in your program, it's ungrammatical. See: https://docs.python.org/2/tutorial/errors.html for examples of programs that have exception handlers to see how to correct this. Alternatively: remove the exception handling altogether. Often, beginners put exception handling in because they don't realize that error messages are awesome. When there's an error, you usually *want* to see the errors show up, at least while you are developing your software. 2. The line: template = arcpy.GetParameteAsText(1) does not look correct because there's a inconsistently-spelled method name "GetParameteAsText". The line that follows immediately afterwards uses "GetParameterAsText": outFolder = arcpy.GetParameterAsText(2) and so this inconsistency attracts my eye. But because of the domain-specificness, I can't say for certain that this is wrong, only that it looks very not-quite-right. From vick1975 at orange.mu Sun Apr 12 08:25:54 2015 From: vick1975 at orange.mu (Vick) Date: Sun, 12 Apr 2015 10:25:54 +0400 Subject: [Tutor] On learning Fortran and C++ for scientific computing In-Reply-To: <201504111656.t3BGuWlD028763@fido.openend.se> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> <201504111656.t3BGuWlD028763@fido.openend.se> Message-ID: <000901d074e9$8829b0e0$987d12a0$@orange.mu> Hello, Thanks for the answer. I quite get the drift of your explanations. But my question was looking for a specific practical answer. As my codes involve a lot of mathematical formulae and some of them require ultra-high precision, hence I was looking for an answer that either Fortran is better suited or Python is better at it. One of the example, I'm thinking about is the commoving distance of redshift in the universe and hence to calculate the radius of the observable universe.see Hogg's paper on it: http://arxiv.org/abs/astro-ph/9905116 This is a mathematical integration of several parameters in cosmology. This particular calculation requires the best precision you can get because by reducing it, you get different answers for the age of the universe and hence the radius of the universe. Example: S for integration S 0 to z ..> dz'/SQRT(omega_radiation (1+z)^4 + omega_matter (1+z)^3 + omega_curvature (1+z)^2 + Omega_dark energy) S 0 to 1e+31....> 1/sqrt(.000086 *(1+z)^4 + .282 * (1+z)^3 - .000086 *(1+z)^2 + .718) if you try this integration you will get completely wrong numbers on computing devices that do not possess ultra-high precision and accuracy. I had to use mpmath with precision of 250 and integration method called Tanh Sinh Quadrature with accuracy 120 to get the desired results. I checked the answer with Mathematica and they concur. But the calculation is done in about 3 seconds on my laptop with intel core i5 at 2.5 GHz with 4 GB RAM. So can Fortran crunch 250 digits numbers in an integration formula under 3 seconds with the same computing parameters as above? Or is Python better at it? Thanks Vick -----Original Message----- From: Laura Creighton [mailto:lac at openend.se] Sent: Saturday, 11 April, 2015 20:57 To: William Ray Wing Cc: Vick; webmaster at python.org; tutor at python.org; lac at openend.se Subject: Re: [Tutor] On learning Fortran and C++ for scientific computing These days, most important scientific libraries are wrapped so that you call call them directly from python. Google for "python bindings " and see if you get any hits. If you have a library that doesn't have python bindings, you can probably make them. Start reading here: http://intermediate-and-advanced-software-carpentry.readthedocs.org/en/lates t/c++-wrapping.html http://scicomp.stackexchange.com/questions/2283/which-package-should-i-use-t o-wrap-modern-fortran-code-with-python to see about wrapping C++ and Fortran code. But chances are somebody has already done it. And for astronomical calculations, I just use pyephem. http://rhodesmill.org/pyephem/index.html It is difficult, and usually pointless to argue with somebody who prefers to use Fortran or C++ about using some other language. People like what they are used to. Moreover, in the case of Fortran and C++, these languages are significantly harder to use than Python, where harder, in this case, means -- the code you write is more prone to errors. Also, it is very easy to write inefficient programs in C++ or Fortran, and scientists, who are not professional programmers are extremely prone to doing this. So while a Fortran or C++ library may be fast (if the library author knew what he or she was doing, or the community has fixed inefficiencies over the years) that doesn't mean that your own C++ or Fortran code is guaranteed to be fast. And, of course, if it takes you 5 times as long in your personal time to write the code, do you actually care how fast the result runs? For very long running calculations, where time is money, the answer may be yes. But if all you want to know is where Uranus is going to be next Thursday so you can point your telescope at it, not a bit. If you need something that runs faster than the standard version of python, you may be able to get it with numpy and the other scientific tools here: http://www.scipy.org/ or with pypy http://speed.pypy.org/ . The number of problems where you can legitimately claim that you badly need the speed that C++ and Fortran provide is shrinking all the time, as machines grow faster. Plus, in modern computing the new challenge is to use multiple cores. It's a very hard problem, and all the old C++ and Fortran libraries were created with the assumption that there is only one core. Right now we don't actually know how to use multiple cores efficiently -- it is hot research in computer science right now, with no particularly good answers. But once we figure out how to do this, all the old C++ and Fortran libraries are probably going to have to be rewritten with this in mind. (A solution that doesn't require such re-writing would, of course be highly desirable, but things are not looking very good on that front.) If your real question is 'would it be desirable to learn C++ and Fortran from a historical perspective, to get an understanding of how important computational libraries in my field are structured', then I am the wrong person to ask. I knew both of these languages before there was a Python. I think learning these langauges will indeed make understanding the old libraries easier, but _using_ these languages to do real work isn't needed. Or rather, if you are one of the people who needs to use them, then you would already know that you are, and why, and wouldn't be asking the question. The world is full of things to learn, so you need to do your own prioritisation of Fortran vs everything else you haven't learned yet. :) Best of luck, Laura Creighton p.s. I gave this topic a more descriptive subject line than 'Hi' but it should still thread with the original. From cybervigilante at gmail.com Sun Apr 12 08:06:31 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 11 Apr 2015 23:06:31 -0700 Subject: [Tutor] why no chaining? Message-ID: I thought I'd get [2,3,4,5] from this but instead I get nothing. Why isn't it chaining? >>> q = list(set([1,2,3,1,4,1,5,1,5])).remove(1) >>> q >>> -- Jim Today is the day that would have been yesterday if tomorrow was today From cybervigilante at gmail.com Sun Apr 12 08:41:59 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 11 Apr 2015 23:41:59 -0700 Subject: [Tutor] Tutor Digest, Vol 134, Issue 32 - amazing range Message-ID: > Range objects are special: not only do they produce values lazily as > needed, but they also support len(), indexing, slicing, and membership > testing, none of which generators are capable of doing: > > Steve ----- That's really cool. Worth making a dumb mistake to find it out ;') Jim Today is the day that would have been yesterday if today was tomorrow From alan.gauld at btinternet.com Sun Apr 12 09:58:41 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 12 Apr 2015 08:58:41 +0100 Subject: [Tutor] why no chaining? In-Reply-To: References: Message-ID: On 12/04/15 07:06, Jim Mooney wrote: > I thought I'd get [2,3,4,5] from this but instead I get nothing. Why isn't > it chaining? > >>>> q = list(set([1,2,3,1,4,1,5,1,5])).remove(1) >>>> q >>>> Because that's just the way it was designed. It's common in Python for methods that modify an object to return None. I don't like it either, but that's the way it is. You need to create a reference to the object then call the method then use the modified object. >>> q = list(set([1,2,3,1,4,1,5,1,5])) >>> q.remove(1) >>> print q Aside: Normally you would use the help() function to find out how methods work and what they return but sadly the documentation for the in-place methods doesn't indicate the return is None. Some of them have a warning that its "IN PLACE" but remove does not. Which is a pity. >>> help([].sort) Help on built-in function sort: sort(...) L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*; cmp(x, y) -> -1, 0, 1 (END) >>> help([].remove) Help on built-in function remove: remove(...) L.remove(value) -- remove first occurrence of value. Raises ValueError if the value is not present. (END) Personally I think it would help if the first lines for these methods read like: remove(...) -> None L.remove...etc As is the case with functions that return a value: Help on built-in function pow in module __builtin__: help(pow) pow(...) pow(x, y[, z]) -> number With two arguments, equivalent to x**y. With three arguments, equivalent to (x**y) % z, but may be more efficient (e.g. for longs). (END) HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From ben+python at benfinney.id.au Sun Apr 12 10:05:16 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Sun, 12 Apr 2015 18:05:16 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate_=28was=3A_Tutor_Digest=2C_Vol_134=2C_Issu?= =?utf-8?q?e_32_-_amazing_range=29?= References: Message-ID: <851tjpydoj.fsf@benfinney.id.au> Jim Mooney writes: > That's really cool. Worth making a dumb mistake to find it out ;') Jim, you are evidently receiving ?digest? messages from this forum. Please disable that in order to receive individual messages, so you can participate properly: responding to individual messages that the rest of us see. Enabling ?digest? mode is only for when you are *certain* that you will never at any point need to respond to any message from the forum. That's not true, so should be turned off. -- \ ?I find the whole business of religion profoundly interesting. | `\ But it does mystify me that otherwise intelligent people take | _o__) it seriously.? ?Douglas Adams | Ben Finney From __peter__ at web.de Sun Apr 12 10:43:35 2015 From: __peter__ at web.de (Peter Otten) Date: Sun, 12 Apr 2015 10:43:35 +0200 Subject: [Tutor] On learning Fortran and C++ for scientific computing References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> <201504111656.t3BGuWlD028763@fido.openend.se> <000901d074e9$8829b0e0$987d12a0$@orange.mu> Message-ID: Vick wrote: > So can Fortran crunch 250 digits numbers in an integration formula under 3 > seconds with the same computing parameters as above? Or is Python better > at it? So by better you mean faster. Pure CPython is usually much slower than Fortran, but as there are many optimised libraries written in C or sometimes even Fortran available for use with CPython, that often doesn't matter. The mpmath documentation states that the library's performance can be improved by using gmp, so in this case the library you should rely on is gmpy or gmpy2. Do you have one of these installed? What does $ python3 -c 'import mpmath.libmp; print(mpmath.libmp.BACKEND)' gmpy print? Once you have your script working with gmp you could simplify it to just the integration, and when you are down to 10 or 20 lines you could challenge your friend to write the Fortran equivalent. If he answers he's not willing to spend a week on the superior Fortran solution, or if he comes up with something that takes 2.7 seconds you see that he was bullshitting you. If his code finishes in 0.1 second and with the correct result, you might consider learning the language -- but keep in mind that to save one hour of execution time you have to run the script more than 1200 times, and when you need 10 minutes longer to write the Fortran than the Python code you may still get a bad deal as your time usually costs more than that of a machine. That said, even though I rarely write any C code knowing C does help me understand what happens in C programs (for example the Python interpreter) and generally broadens the horizon. Therefore I'd recommend learning C (or Fortran) anyway if you are interested in the computing part of your research. From timomlists at gmail.com Sun Apr 12 12:16:58 2015 From: timomlists at gmail.com (Timo) Date: Sun, 12 Apr 2015 12:16:58 +0200 Subject: [Tutor] why no chaining? In-Reply-To: References: Message-ID: <552A461A.1030503@gmail.com> Op 12-04-15 om 09:58 schreef Alan Gauld: > > Aside: > Normally you would use the help() function to find out > how methods work and what they return but sadly the > documentation for the in-place methods doesn't indicate > the return is None. Some of them have a warning that > its "IN PLACE" but remove does not. Which is a pity. > > >>> help([].sort) > Help on built-in function sort: > > sort(...) > L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*; > cmp(x, y) -> -1, 0, 1 > (END) > > >>> help([].remove) > Help on built-in function remove: > > remove(...) > L.remove(value) -- remove first occurrence of value. > Raises ValueError if the value is not present. > (END) > > Personally I think it would help if the first lines > for these methods read like: > > remove(...) -> None > L.remove...etc Are you using Python 2? Because this is what I get in Python 3: remove(...) L.remove(value) -> None -- remove first occurrence of value. Raises ValueError if the value is not present. The same for help(list.sort) BTW. Timo From lac at openend.se Sun Apr 12 13:29:56 2015 From: lac at openend.se (Laura Creighton) Date: Sun, 12 Apr 2015 13:29:56 +0200 Subject: [Tutor] On learning Fortran and C++ for scientific computing In-Reply-To: Message from "Vick" of "Sun, 12 Apr 2015 10:25:54 +0400." <000901d074e9$8829b0e0$987d12a0$@orange.mu> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> <201504111656.t3BGuWlD028763@fido.openend.se><000901d074e9$8829b0e0$987d12a0$@orange.mu> Message-ID: <201504121129.t3CBTuXc028842@fido.openend.se> In a message of Sun, 12 Apr 2015 10:25:54 +0400, "Vick" writes: >S 0 to 1e+31....> 1/sqrt(.000086 *(1+z)^4 + .282 * (1+z)^3 - .000086 >*(1+z)^2 + .718) if you try this integration you will get completely >wrong numbers on computing devices that do not possess ultra-high precision >and accuracy. Python is as accurate as you can get, every bit as accurate as C++ or Fortran. >I had to use mpmath with precision of 250 and integration method called Tanh >Sinh Quadrature with accuracy 120 to get the desired results. I checked the >answer with Mathematica and they concur. But the calculation is done in >about 3 seconds on my laptop with intel core i5 at 2.5 GHz with 4 GB RAM. >So can Fortran crunch 250 digits numbers in an integration formula under 3 >seconds with the same computing parameters as above? Or is Python better at >it? Some of us who were unhappy with the performance of python wrote pypy. (I am one of the people, so very much biased here.) PyPy uses a just-in-time compiler to get its speed. If you want to look at the speed of pypy vs the speed of CPython (which is what we call the particular implementation(s) of python you are using, because it is written in C) you can take a look at these pages. http://speed.pypy.org/ Click on a benchmark, and see the code, and see how much faster we are than CPython. Mathematical formulae are what we are very, very good at. Indeed we are often better than some old Fortran library -- so we have users who are busy rewriting their code in Python in order to use pypy for the increased speed of mathematical computation. If all you are doing is pure math -- and not going out, for instance and trying to graph this thing at the same time -- then we can probably give you speed which is equivalent to C. But this assumes that you can write this code where the heavy calculating is done inside a loop, which is executed many times, because that is what PyPy optimises. If all you have is straight in-line executed-one-time-only code, there will be no speed win for you. Also, the jit takes time to warm up. It has to set up its own internal bookkeeping before it can get to work on your code. So if your code doesn't take very long to run, it may run slower in pypy -- because the savings your get are competely swallowed up in the setup costs. However, it is easy to find out. You can get pypy here: http://pypy.org/download.html It's a perfectly compliant, working python. The version compatible with 3.2.5 is not as speedy as the one compatible with 2.7. So just run your python code with this -- it should run completely unchanged -- and see how fast it is. If you are still unhappy with the performance, post your code to pypy-dev at python.org and we can give you suggestions on how to tune your python code for better performance under pypy. If you expose a place where pypy ought to be fast, but isn't, we will fix pypy and get you a working faster binary. But I think any more talk about pypy belongs on the pypy-dev mailing list. Laura Creighton From lac at openend.se Sun Apr 12 12:56:45 2015 From: lac at openend.se (Laura Creighton) Date: Sun, 12 Apr 2015 12:56:45 +0200 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate_=28was=3A_Tutor_Digest=2C_Vol_134?= =?utf-8?q?=2C_Issue_32_-_amazing_range=29?= In-Reply-To: Message from Ben Finney of "Sun, 12 Apr 2015 18:05:16 +1000." <851tjpydoj.fsf@benfinney.id.au> References: <851tjpydoj.fsf@benfinney.id.au> Message-ID: <201504121056.t3CAujOD027839@fido.openend.se> In a message of Sun, 12 Apr 2015 18:05:16 +1000, Ben Finney writes: >Jim, you are evidently receiving ?digest? messages from this forum. > >Please disable that in order to receive individual messages, so you can >participate properly: responding to individual messages that the rest of >us see. > >Enabling ?digest? mode is only for when you are *certain* that you will >never at any point need to respond to any message from the forum. That's >not true, so should be turned off. Or see if your mailer, like mine, has an option for bursting digests in place. Bursting is splitting a digest into individual messages so that you can reply to them individually. (Very few mailers do this, which is a real shame. And every one I know of calls this 'bursting'.) Then please burst your digests before you reply to them. Laura Creighton From alan.gauld at btinternet.com Sun Apr 12 13:39:40 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 12 Apr 2015 12:39:40 +0100 Subject: [Tutor] why no chaining? In-Reply-To: <552A461A.1030503@gmail.com> References: <552A461A.1030503@gmail.com> Message-ID: On 12/04/15 11:16, Timo wrote: >> Personally I think it would help if the first lines >> for these methods read like: >> >> remove(...) -> None >> L.remove...etc > Are you using Python 2? Because this is what I get in Python 3: Yes, I just fired up the default python which is 2.7. I never thought to check what Python 3 help said. Good to see its been addressed., -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cybervigilante at gmail.com Sun Apr 12 20:03:07 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sun, 12 Apr 2015 11:03:07 -0700 Subject: [Tutor] still breaking chains Message-ID: If join returns a string, why am I getting a syntax error when I try to slice it? >>> 'alfabeta'[2:5] 'fab' >>> ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] SyntaxError: invalid syntax -- Jim From danny.yoo at gmail.com Mon Apr 13 01:05:02 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Sun, 12 Apr 2015 16:05:02 -0700 Subject: [Tutor] still breaking chains In-Reply-To: References: Message-ID: On Apr 12, 2015 4:00 PM, "Jim Mooney" wrote: > > If join returns a string, why am I getting a syntax error when I try to > slice it? > > >>> 'alfabeta'[2:5] > 'fab' > >>> ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] > SyntaxError: invalid syntax If you're seeing a SyntaxError, don't look for explanations that are semantic. Look for syntax. In this case, note that the list of characters had not been closed with a right bracket yet. Best of wishes! From ben+python at benfinney.id.au Mon Apr 13 01:44:32 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Mon, 13 Apr 2015 09:44:32 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate?= References: <851tjpydoj.fsf@benfinney.id.au> <201504121056.t3CAujOD027839@fido.openend.se> Message-ID: <85sic4x673.fsf@benfinney.id.au> Laura Creighton writes: > In a message of Sun, 12 Apr 2015 18:05:16 +1000, Ben Finney writes: > >Please disable that in order to receive individual messages, so you > >can participate properly: responding to individual messages that the > >rest of us see. > > Or see if your mailer, like mine, has an option for bursting digests > in place. Bursting is splitting a digest into individual messages so > that you can reply to them individually. That's an interesting feature. It's not sufficient though: the resulting messages lack the full header of each message, so any reply will not be properly marked as a response to the original. The only way to participate properly in a discussion on a mailing list is to respond to the actual messages that were sent. And that's only possible if you disable ?digest? mode beforehand. -- \ ?Those who write software only for pay should go hurt some | `\ other field.? ?Erik Naggum, in _gnu.misc.discuss_ | _o__) | Ben Finney From ben+python at benfinney.id.au Mon Apr 13 01:47:17 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Mon, 13 Apr 2015 09:47:17 +1000 Subject: [Tutor] still breaking chains References: Message-ID: <85oamsx62i.fsf@benfinney.id.au> Jim Mooney writes: > If join returns a string, why am I getting a syntax error when I try to > slice it? > > >>> 'alfabeta'[2:5] > 'fab' > >>> ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] > SyntaxError: invalid syntax This demonstrates the primary problem with so-called ?chaining?. Your statement is too complex, and you have misunderstood where in that statement the error is. Break the statement into at least two: get the result of the ?join?, and then in the next statement slice that value. You'll see where the error was. One important principle to follow is to write your statements to be very simple, so that when something goes wrong it is as easy as possible to read the statement and understand what it *actually* says. Chaining long strings of operations together in a single statement goes directly against that principle, and hence is to be avoided. -- \ ?[T]he speed of response of the internet will re-introduce us | `\ to that from which our political systems have separated us for | _o__) so long, the consequences of our own actions.? ?Douglas Adams | Ben Finney From steve at pearwood.info Mon Apr 13 03:11:52 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 13 Apr 2015 11:11:52 +1000 Subject: [Tutor] still breaking chains In-Reply-To: References: Message-ID: <20150413011152.GO5760@ando.pearwood.info> On Sun, Apr 12, 2015 at 11:03:07AM -0700, Jim Mooney wrote: > If join returns a string, why am I getting a syntax error when I try to > slice it? Because you have a syntax error. Syntax error means you have written something which the Python compiler cannot understand, because the syntax is wrong, mangled or confused, or something is missing from the line of code. (If the missing element is a closing bracket, brace or parethesis, the compiler may not report the error until the line *after* the offending line.) An English example: "I would like a cup of coffee" -- correct syntax "would coffee I cup like" -- syntax error Human beings are more flexible with syntax and can sometimes decipher rather mangled invalid sentences (e.g. most of us can understand Yoda) but programming language compilers are less flexible and require you to be pedantically correct: + 1 2 # syntax error function(x y) # syntax error '-'.join['a', 'b') # syntax error This does not mean that Python cannot add numbers, call functions, or join substrings. It means the compiler cannot understand my mangled code. Fix the syntax: 1 + 2 function(x, y) '-'.join(['a', 'b']) In your example: > >>> 'alfabeta'[2:5] > 'fab' > >>> ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] > SyntaxError: invalid syntax I believe you have deleted what you might have thought was a blank line, but actually gives you a hint as to what the error is. When I try to run that, I get this: py> ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] File "", line 1 ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] ^ SyntaxError: invalid syntax Look carefully at the "blank" line: it isn't actually blank. Way over on the right hand side you will see a caret ^ pointing to the spot where the compiler first noticed something it could not understand. In your email, it may not line up, but in the interactive interpreter the caret will line up with ) the closing round bracket. Why? Because before you close the method call ''.join( ) you have to close the list [ ]: ''.join([...]) # okay ''.join([...) # syntax error It is sad that the Python compiler does not report a more useful error message here. It would be awesome if it would report: SyntaxError: missing closing bracket ] but we should count our blessing that we get anything at all. -- Steve From robertvstepp at gmail.com Mon Apr 13 04:21:06 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 12 Apr 2015 21:21:06 -0500 Subject: [Tutor] still breaking chains In-Reply-To: <85oamsx62i.fsf@benfinney.id.au> References: <85oamsx62i.fsf@benfinney.id.au> Message-ID: On Sun, Apr 12, 2015 at 6:47 PM, Ben Finney wrote: [...] > One important principle to follow is to write your statements to be very > simple, so that when something goes wrong it is as easy as possible to > read the statement and understand what it *actually* says. +1! This principle I have found to be incredibly helpful as I continue to learn Python and better programming in general. Where it especially pays dividends for me is when I must go back to where I was coding after an extended interruption. I find that when I have followed this principle I have a much better chance of *immediately* understanding my intent, then when I have to decipher my thoughts from a "one-liner" that might occupy less space, but where its complexity has me pausing in thought to be sure I understand what I actually was trying to do. -- boB From cybervigilante at gmail.com Mon Apr 13 01:44:22 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sun, 12 Apr 2015 16:44:22 -0700 Subject: [Tutor] still breaking chains In-Reply-To: References: Message-ID: On Apr 12, 2015 4:00 PM, "Jim Mooney" wrote: > > > > If join returns a string, why am I getting a syntax error when I try to > > slice it? > > > > >>> 'alfabeta'[2:5] > > 'fab' > > >>> ''.join(['a', 'l', 'f', 'a', 'b', 'e', 't', 'a')[2:5] > > SyntaxError: invalid syntax > > If you're seeing a SyntaxError, don't look for explanations that are > semantic. Look for syntax.In this case, note that the list of characters > had not been closed with a right bracket yet. > > Best of wishes! > Eeek! How did I miss that? Won't be the first time I confused mistyping with misunderstanding ;') -- Jim From cybervigilante at gmail.com Mon Apr 13 01:51:04 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sun, 12 Apr 2015 16:51:04 -0700 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate?= In-Reply-To: <85sic4x673.fsf@benfinney.id.au> References: <851tjpydoj.fsf@benfinney.id.au> <201504121056.t3CAujOD027839@fido.openend.se> <85sic4x673.fsf@benfinney.id.au> Message-ID: > That's an interesting feature. It's not sufficient though: the resulting > messages lack the full header of each message, so any reply will not be > properly marked as a response to the original. > > The only way to participate properly in a discussion on a mailing list > is to respond to the actual messages that were sent. And that's only > possible if you disable ?digest? mode beforehand. > https://mail.python.org/mailman/listinfo/tutor > Well, I've disabled digest and assume I should Reply to All and underpost. How does that look? -- Jim "Stop, Harold! That bagel has radishes!" "Thank God, Mary - you've saved me again!" From cybervigilante at gmail.com Mon Apr 13 02:02:57 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sun, 12 Apr 2015 17:02:57 -0700 Subject: [Tutor] still breaking chains In-Reply-To: <85oamsx62i.fsf@benfinney.id.au> References: <85oamsx62i.fsf@benfinney.id.au> Message-ID: > Chaining long strings of operations together in a single statement goes > directly against that principle, and hence is to be avoided. > > Ben Finney > > A hard habit to break after using jQuery as a webmaster ;') -- Jim "Stop, Harold! That bagel has radishes!" "Thank God, Mary - you've saved me again!" From ben+python at benfinney.id.au Mon Apr 13 10:35:52 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Mon, 13 Apr 2015 18:35:52 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate?= References: <851tjpydoj.fsf@benfinney.id.au> <201504121056.t3CAujOD027839@fido.openend.se> <85sic4x673.fsf@benfinney.id.au> Message-ID: <85y4lwv313.fsf@benfinney.id.au> Jim Mooney writes: > > The only way to participate properly in a discussion on a mailing > > list is to respond to the actual messages that were sent. And that's > > only possible if you disable ?digest? mode beforehand. > > Well, I've disabled digest and assume I should Reply to All and underpost. > How does that look? Looks great, thank you. The cherry on top is: Preserve the attribution line (the line that says who wrote the material you're quoting) on quoted material you keep. Especially when there are several nested levels, ? like here ? keeping the attribution lines matching the quoted material helps to make sense of it all. -- \ ?The long-term solution to mountains of waste is not more | `\ landfill sites but fewer shopping centres.? ?Clive Hamilton, | _o__) _Affluenza_, 2005 | Ben Finney From alan.gauld at btinternet.com Mon Apr 13 12:38:59 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 13 Apr 2015 11:38:59 +0100 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate?= In-Reply-To: References: <851tjpydoj.fsf@benfinney.id.au> <201504121056.t3CAujOD027839@fido.openend.se> <85sic4x673.fsf@benfinney.id.au> Message-ID: On 13/04/15 00:51, Jim Mooney wrote: >> The only way to participate properly in a discussion on a mailing list >> is to respond to the actual messages that were sent. And that's only >> possible if you disable ?digest? mode beforehand. > > Well, I've disabled digest and assume I should Reply to All and underpost. > How does that look? Looks goods. BTW if you use digest to reduce clutter in the inbox you might find it worthwhile to create a folder for tutor mail and set up a rule to move all received mail from tutor to that folder. Then read that folder at your leisure. Alternatively use the News feed from gmane.org -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From beachkidken at gmail.com Mon Apr 13 14:11:46 2015 From: beachkidken at gmail.com (Ken G.) Date: Mon, 13 Apr 2015 08:11:46 -0400 Subject: [Tutor] Function not returning 05 as string Message-ID: <552BB282.3060303@gmail.com> I am sure there is an simple explanation but when I input 5 (as integer), resulting in 05 (as string), I get zero as the end result. When running the code: START OF PROGRAM: Enter the 1st number: 5 05 0 END OF PROGRAM: START OF CODE: import sys def numberentry(): print number01 = raw_input("Enter the 1st number: ") if number01 == "0": sys.exit() if len(number01) == 1: number01 = "0" + number01 print print number01 return(number01) number01 = 0 numberentry() print print number01 END OF CODE: From davea at davea.name Mon Apr 13 14:18:55 2015 From: davea at davea.name (Dave Angel) Date: Mon, 13 Apr 2015 08:18:55 -0400 Subject: [Tutor] Function not returning 05 as string In-Reply-To: <552BB282.3060303@gmail.com> References: <552BB282.3060303@gmail.com> Message-ID: <552BB42F.4000009@davea.name> On 04/13/2015 08:11 AM, Ken G. wrote: > I am sure there is an simple explanation but when I input > 5 (as integer), resulting in 05 (as string), I get zero as the end > result. When running the code: > > START OF PROGRAM: > Enter the 1st number: 5 > > 05 > > 0 > END OF PROGRAM: > > START OF CODE: > import sys > > def numberentry(): > print > number01 = raw_input("Enter the 1st number: ") > if number01 == "0": > sys.exit() > if len(number01) == 1: > number01 = "0" + number01 > print > print number01 > return(number01) > > number01 = 0 What is this line intended to do? > numberentry() Where are you intending to store the return value? Currently, you're just throwing it away. > print > print number01 This variable has no relation to the one in the function. In fact, I'd recommend you use a different name, to make that clear. > END OF CODE: -- DaveA From jarod_v6 at libero.it Mon Apr 13 14:29:07 2015 From: jarod_v6 at libero.it (jarod_v6 at libero.it) Date: Mon, 13 Apr 2015 14:29:07 +0200 (CEST) Subject: [Tutor] Regular expression on python Message-ID: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> Dear all. I would like to extract from some file some data. The line I'm interested is this: Input Read Pairs: 2127436 Both Surviving: 1795091 (84.38%) Forward Only Surviving: 17315 (0.81%) Reverse Only Surviving: 6413 (0.30%) Dropped: 308617 (14.51%) with open("255.trim.log","r") as p: for i in p: lines= i.strip("\t") if lines.startswith("Input"): tp = lines.split("\t") print re.findall("Input\d",str(tp)) So I started to find ":" from the row: with open("255.trim.log","r") as p: for i in p: lines= i.strip("\t") if lines.startswith("Input"): tp = lines.split("\t") print re.findall(":",str(tp[0])) And I'm able to find, but when I try to take the number using \d not work. Someone can explain why? How can extract the numbers from this row.? thanks so much= From beachkidken at gmail.com Mon Apr 13 14:34:09 2015 From: beachkidken at gmail.com (Ken G.) Date: Mon, 13 Apr 2015 08:34:09 -0400 Subject: [Tutor] Function not returning 05 as string In-Reply-To: <552BB42F.4000009@davea.name> References: <552BB282.3060303@gmail.com> <552BB42F.4000009@davea.name> Message-ID: <552BB7C1.4040705@gmail.com> On 04/13/2015 08:18 AM, Dave Angel wrote: > On 04/13/2015 08:11 AM, Ken G. wrote: >> I am sure there is an simple explanation but when I input >> 5 (as integer), resulting in 05 (as string), I get zero as the end >> result. When running the code: >> >> START OF PROGRAM: >> Enter the 1st number: 5 >> >> 05 >> >> 0 >> END OF PROGRAM: >> >> START OF CODE: >> import sys >> >> def numberentry(): >> print >> number01 = raw_input("Enter the 1st number: ") >> if number01 == "0": >> sys.exit() >> if len(number01) == 1: >> number01 = "0" + number01 >> print >> print number01 >> return(number01) >> >> number01 = 0 > > What is this line intended to do? NameError: name 'number01' is not defined > >> numberentry() > > Where are you intending to store the return value? Currently, you're > just throwing it away. I am not sending anything to the def routine but expected an answer in return. > >> print >> print number01 > > This variable has no relation to the one in the function. In fact, > I'd recommend you use a different name, to make that clear. Do not use return at end of routine? I am lost there. > >> END OF CODE: > > Thanks for answering. Ken From __peter__ at web.de Mon Apr 13 14:44:09 2015 From: __peter__ at web.de (Peter Otten) Date: Mon, 13 Apr 2015 14:44:09 +0200 Subject: [Tutor] Function not returning 05 as string References: <552BB282.3060303@gmail.com> Message-ID: Ken G. wrote: > I am sure there is an simple explanation but when I input > 5 (as integer), resulting in 05 (as string), I get zero as the end > result. When running the code: > > START OF PROGRAM: > Enter the 1st number: 5 > > 05 > > 0 > END OF PROGRAM: > > START OF CODE: > import sys > > def numberentry(): > print > number01 = raw_input("Enter the 1st number: ") > if number01 == "0": > sys.exit() > if len(number01) == 1: > number01 = "0" + number01 > print > print number01 > return(number01) > > number01 = 0 > numberentry() > print > print number01 > END OF CODE: Let's simplify that and run it in the interactive interpreter: >>> x = 0 >>> def f(): ... x = 5 ... print x ... >>> f() 5 >>> x 0 You are seeing two different values because there are two separate namespaces. The x = 0 lives in the "global" namespace of the module while the other x = 5 exists in the "local" namespace of the function, is only visible from a specific invocation of f() and only while that specific invocation of f() is executed. If you want see the value of a global variable from within a function you must not rebind it: >>> def g(): ... print x ... >>> f() 5 >>> x = 42 >>> f() 5 If you want to update a global variable you should do that explicitly >>> def h(): ... return "foo" ... >>> x = h() >>> x 'foo' but there is also the option to declare it as global inside the function: >>> def k(): ... global x ... x = "bar" ... >>> k() >>> x 'bar' The global keyword is generally overused by newbies and tends to make your programs hard to maintain. Try it a few times to ensure that you understand how it works -- and then forget about it and never use it again ;) Back to your original code -- assuming that you want to update the global name 'number01' you could rewrite it like this: def numberentry(): digit = raw_input("Enter the 1st number: ") if len(digit) != 1 or not digit.isdigit(): raise ValueError("Not an allowed input: {!r}".format(digit)) return digit.zfill(2) number01 = numberentry() if number01 != "00": print number01 From dpalao.python at gmail.com Mon Apr 13 14:46:08 2015 From: dpalao.python at gmail.com (David Palao) Date: Mon, 13 Apr 2015 14:46:08 +0200 Subject: [Tutor] Function not returning 05 as string In-Reply-To: <552BB282.3060303@gmail.com> References: <552BB282.3060303@gmail.com> Message-ID: Hello, In the code that you posted, as it is, you are: 1) defining a function (numberentry) 2) defining a global variable (number01) and setting it to 0 3) calling numberentry discarding the result 4) printing the value of the global variable number01 I would guess that you want to store the result of the function and print it. Is that correct? Best 2015-04-13 14:11 GMT+02:00 Ken G. : > I am sure there is an simple explanation but when I input > 5 (as integer), resulting in 05 (as string), I get zero as the end > result. When running the code: > > START OF PROGRAM: > Enter the 1st number: 5 > > 05 > > 0 > END OF PROGRAM: > > START OF CODE: > import sys > > def numberentry(): > print > number01 = raw_input("Enter the 1st number: ") > if number01 == "0": > sys.exit() > if len(number01) == 1: > number01 = "0" + number01 > print > print number01 > return(number01) > > number01 = 0 > numberentry() > print > print number01 > END OF CODE: > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From steve at pearwood.info Mon Apr 13 14:56:32 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 13 Apr 2015 22:56:32 +1000 Subject: [Tutor] Function not returning 05 as string In-Reply-To: <552BB282.3060303@gmail.com> References: <552BB282.3060303@gmail.com> Message-ID: <20150413125631.GA5663@ando.pearwood.info> On Mon, Apr 13, 2015 at 08:11:46AM -0400, Ken G. wrote: > I am sure there is an simple explanation but when I input > 5 (as integer), resulting in 05 (as string), I get zero as the end > result. When running the code: > number01 = 0 Here you set the variable "number01" to the int 0. > numberentry() Here you call the function. It returns "05", but you don't do anything with it, so it just gets dropped on the floor and thrown away. > print > print number01 Here you print the variable number01, which is still the int 0, unchanged. I think where you are mislead is that you are not aware, or have forgotten, that global variables and local variables are different. So a variable "x" outside of a function and a variable "x" inside a function are different variables. Think of functions being like Los Vegas: "what happens in Vegas, stays in Vegas" -- function local variables don't leak out and have effects outside of the function except via the "return" statement, and even then only if the caller assigns the result to another variable: function() # return result is thrown away x = function() # return result is assigned to x The other way to have an effect outside of the function is to use global variables, and the global keyword. This is occasionally necessary, but I strongly recommend against it: it is poor programming practice and a bad habit to get into. -- Steve From beachkidken at gmail.com Mon Apr 13 15:10:55 2015 From: beachkidken at gmail.com (Ken G.) Date: Mon, 13 Apr 2015 09:10:55 -0400 Subject: [Tutor] Function not returning 05 as string [SOLVED] In-Reply-To: <20150413125631.GA5663@ando.pearwood.info> References: <552BB282.3060303@gmail.com> <20150413125631.GA5663@ando.pearwood.info> Message-ID: <552BC05F.8080702@gmail.com> On 04/13/2015 08:56 AM, Steven D'Aprano wrote: > On Mon, Apr 13, 2015 at 08:11:46AM -0400, Ken G. wrote: >> I am sure there is an simple explanation but when I input >> 5 (as integer), resulting in 05 (as string), I get zero as the end >> result. When running the code: >> number01 = 0 > Here you set the variable "number01" to the int 0. > >> numberentry() > Here you call the function. It returns "05", but you don't do anything > with it, so it just gets dropped on the floor and thrown away. > >> print >> print number01 > Here you print the variable number01, which is still the int 0, > unchanged. > > I think where you are mislead is that you are not aware, or have > forgotten, that global variables and local variables are different. So a > variable "x" outside of a function and a variable "x" inside a function > are different variables. Think of functions being like Los Vegas: "what > happens in Vegas, stays in Vegas" -- function local variables don't leak > out and have effects outside of the function except via the "return" > statement, and even then only if the caller assigns the result to > another variable: > > function() # return result is thrown away > x = function() # return result is assigned to x > > > The other way to have an effect outside of the function is to use global > variables, and the global keyword. This is occasionally necessary, but I > strongly recommend against it: it is poor programming practice and a bad > habit to get into. > > Thanks for all the replies. I will keep at it. Again, thanks. Ken From jarod_v6 at libero.it Mon Apr 13 16:30:50 2015 From: jarod_v6 at libero.it (jarod_v6 at libero.it) Date: Mon, 13 Apr 2015 16:30:50 +0200 (CEST) Subject: [Tutor] R: Tutor Digest, Vol 134, Issue 36 Message-ID: <1183122906.1592361428935450788.JavaMail.httpd@webmail-58.iol.local> At the moment I use this way to resolve my question: re.findall(r'(\w+):\W(\d+)',str(tp[0])) However please gave me you suggestion on how to improve my ability to use regular expression on python Thanks so much! From vick1975 at orange.mu Mon Apr 13 18:45:21 2015 From: vick1975 at orange.mu (Vick) Date: Mon, 13 Apr 2015 20:45:21 +0400 Subject: [Tutor] On learning Fortran and C++ for scientific computing In-Reply-To: <201504121129.t3CBTuXc028842@fido.openend.se> References: <000001d07453$997a48a0$cc6ed9e0$@orange.mu> <201504111656.t3BGuWlD028763@fido.openend.se><000901d074e9$8829b0e0$987d12a0$@orange.mu> <201504121129.t3CBTuXc028842@fido.openend.se> Message-ID: <000001d07609$4306b280$c9141780$@orange.mu> Hi, Thanks Vick -----Original Message----- From: Laura Creighton [mailto:lac at openend.se] Sent: Sunday, 12 April, 2015 15:30 To: Vick Cc: 'Laura Creighton'; 'William Ray Wing'; webmaster at python.org; tutor at python.org; lac at openend.se Subject: Re: [Tutor] On learning Fortran and C++ for scientific computing In a message of Sun, 12 Apr 2015 10:25:54 +0400, "Vick" writes: >S 0 to 1e+31....> 1/sqrt(.000086 *(1+z)^4 + .282 * (1+z)^3 - .000086 >*(1+z)^2 + .718) if you try this integration you will get completely >wrong numbers on computing devices that do not possess ultra-high >precision and accuracy. Python is as accurate as you can get, every bit as accurate as C++ or Fortran. >I had to use mpmath with precision of 250 and integration method called >Tanh Sinh Quadrature with accuracy 120 to get the desired results. I >checked the answer with Mathematica and they concur. But the >calculation is done in about 3 seconds on my laptop with intel core i5 at 2.5 GHz with 4 GB RAM. >So can Fortran crunch 250 digits numbers in an integration formula >under 3 seconds with the same computing parameters as above? Or is >Python better at it? Some of us who were unhappy with the performance of python wrote pypy. (I am one of the people, so very much biased here.) PyPy uses a just-in-time compiler to get its speed. If you want to look at the speed of pypy vs the speed of CPython (which is what we call the particular implementation(s) of python you are using, because it is written in C) you can take a look at these pages. http://speed.pypy.org/ Click on a benchmark, and see the code, and see how much faster we are than CPython. Mathematical formulae are what we are very, very good at. Indeed we are often better than some old Fortran library -- so we have users who are busy rewriting their code in Python in order to use pypy for the increased speed of mathematical computation. If all you are doing is pure math -- and not going out, for instance and trying to graph this thing at the same time -- then we can probably give you speed which is equivalent to C. But this assumes that you can write this code where the heavy calculating is done inside a loop, which is executed many times, because that is what PyPy optimises. If all you have is straight in-line executed-one-time-only code, there will be no speed win for you. Also, the jit takes time to warm up. It has to set up its own internal bookkeeping before it can get to work on your code. So if your code doesn't take very long to run, it may run slower in pypy -- because the savings your get are competely swallowed up in the setup costs. However, it is easy to find out. You can get pypy here: http://pypy.org/download.html It's a perfectly compliant, working python. The version compatible with 3.2.5 is not as speedy as the one compatible with 2.7. So just run your python code with this -- it should run completely unchanged -- and see how fast it is. If you are still unhappy with the performance, post your code to pypy-dev at python.org and we can give you suggestions on how to tune your python code for better performance under pypy. If you expose a place where pypy ought to be fast, but isn't, we will fix pypy and get you a working faster binary. But I think any more talk about pypy belongs on the pypy-dev mailing list. Laura Creighton From cbc at unc.edu Mon Apr 13 19:48:41 2015 From: cbc at unc.edu (Chris Calloway) Date: Mon, 13 Apr 2015 13:48:41 -0400 Subject: [Tutor] Python and Django Web Engineering Class Message-ID: <552C0179.6040103@unc.edu> Not for everybody, but this just popped up in my neck of the woods, organized by members of my Python user group, and I though there might be a few people here looking for something like this: http://astrocodeschool.com/ It's one of those intensive multi-week code school formats that aren't inexpensive. But it's taught by the primary Python instructor at UNC. The school is also licensed by the State of North Carolina and sponsored by Caktus Group, the largest Django development firm. -- Sincerely, Chris Calloway, Applications Analyst UNC Renaissance Computing Institute 100 Europa Drive, Suite 540, Chapel Hill, NC 27517 (919) 599-3530 From lac at openend.se Mon Apr 13 16:01:52 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 13 Apr 2015 16:01:52 +0200 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest=E2=80=9D_mode_in?= =?utf-8?q?_order_to_participate?= In-Reply-To: Message from Jim Mooney of "Sun, 12 Apr 2015 16:51:04 -0700." References: <851tjpydoj.fsf@benfinney.id.au> <201504121056.t3CAujOD027839@fido.openend.se> <85sic4x673.fsf@benfinney.id.au> Message-ID: <201504131401.t3DE1q43012657@fido.openend.se> In a message of Sun, 12 Apr 2015 16:51:04 -0700, Jim Mooney writes: >Well, I've disabled digest and assume I should Reply to All and underpost. >How does that look? > >-- >Jim Looks great here. Laura From alan.gauld at btinternet.com Mon Apr 13 20:42:03 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 13 Apr 2015 19:42:03 +0100 Subject: [Tutor] Regular expression on python In-Reply-To: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> Message-ID: On 13/04/15 13:29, jarod_v6 at libero.it wrote: > Input Read Pairs: 2127436 Both Surviving: 1795091 (84.38%) Forward Only Surviving: 17315 (0.81%) Reverse Only Surviving: 6413 (0.30%) Dropped: 308617 (14.51%) Its not clear where the tabs are in this line. But if they are after the numbers, like so: Input Read Pairs: 2127436 \t Both Surviving: 1795091 (84.38%) \t Forward Only Surviving: 17315 (0.81%) \t Reverse Only Surviving: 6413 (0.30%) \t Dropped: 308617 (14.51%) Then you may not need to use regular expressions. Simply split by tab then split by : And if the 'number' contains parens split again by space > with open("255.trim.log","r") as p: > for i in p: > lines= i.strip("\t") lines is a bad name here since its only a single line. In fact I'd lose the 'i' variable and just use for line in p: > if lines.startswith("Input"): > tp = lines.split("\t") > print re.findall("Input\d",str(tp)) Input is not followed by a number. You need a more powerful pattern. Which is why I recommend trying to solve it as far as possible without using regex. > So I started to find ":" from the row: > with open("255.trim.log","r") as p: > for i in p: > lines= i.strip("\t") > if lines.startswith("Input"): > tp = lines.split("\t") > print re.findall(":",str(tp[0])) Does finding the colons really help much? Or at least, does it help any more than splitting by colon would? > And I'm able to find, but when I try to take the number using \d not work. > Someone can explain why? Because your pattern doesn't match the string. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Mon Apr 13 21:14:16 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 13 Apr 2015 20:14:16 +0100 Subject: [Tutor] Regular expression on python In-Reply-To: References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> Message-ID: On 13/04/15 19:42, Alan Gauld wrote: >> if lines.startswith("Input"): >> tp = lines.split("\t") >> print re.findall("Input\d",str(tp)) > > Input is not followed by a number. You need a more powerful pattern. > Which is why I recommend trying to solve it as far as possible > without using regex. I also just realised that you call split there then take the str() of the result. That means you are searching the string representation of a list, which doesn't seem to make much sense? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Tue Apr 14 03:48:16 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 14 Apr 2015 11:48:16 +1000 Subject: [Tutor] Regular expression on python In-Reply-To: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> Message-ID: <20150414014816.GC5663@ando.pearwood.info> On Mon, Apr 13, 2015 at 02:29:07PM +0200, jarod_v6 at libero.it wrote: > Dear all. > I would like to extract from some file some data. > The line I'm interested is this: > > Input Read Pairs: 2127436 Both Surviving: 1795091 (84.38%) Forward > Only Surviving: 17315 (0.81%) Reverse Only Surviving: 6413 (0.30%) > Dropped: 308617 (14.51%) Some people, when confronted with a problem, think "I know, I'll use regular expressions." Now they have two problems. -- Jamie Zawinski ? I swear that Perl has been a blight on an entire generation of programmers. All they know is regular expressions, so they turn every data processing problem into a regular expression. Or at least they *try* to. As you have learned, regular expressions are hard to read, hard to write, and hard to get correct. Let's write some Python code instead. def extract(line): # Extract key:number values from the string. line = line.strip() # Remove leading and trailing whitespace. words = line.split() accumulator = [] # Collect parts of the string we care about. for word in words: if word.startswith('(') and word.endswith('%)'): # We don't care about percentages in brackets. continue try: n = int(word) except ValueError: accumulator.append(word) else: accumulator.append(n) # Now accumulator will be a list of strings and ints: # e.g. ['Input', 'Read', 'Pairs:', 1234, 'Both', 'Surviving:', 1000] # Collect consecutive strings as the key, int to be the value. results = {} keyparts = [] for item in accumulator: if isinstance(item, int): key = ' '.join(keyparts) keyparts = [] if key.endswith(':'): key = key[:-1] results[key] = item else: keyparts.append(item) # When we have finished processing, the keyparts list should be empty. if keyparts: extra = ' '.join(keyparts) print('Warning: found extra text at end of line "%s".' % extra) return results Now let me test it: py> line = ('Input Read Pairs: 2127436 Both Surviving: 1795091' ... ' (84.38%) Forward Only Surviving: 17315 (0.81%)' ... ' Reverse Only Surviving: 6413 (0.30%) Dropped:' ... ' 308617 (14.51%)\n') py> py> print(line) Input Read Pairs: 2127436 Both Surviving: 1795091 (84.38%) Forward Only Surviving: 17315 (0.81%) Reverse Only Surviving: 6413 (0.30%) Dropped: 308617 (14.51%) py> extract(line) {'Dropped': 308617, 'Both Surviving': 1795091, 'Reverse Only Surviving': 6413, 'Forward Only Surviving': 17315, 'Input Read Pairs': 2127436} Remember that dicts are unordered. All the data is there, but in arbitrary order. Now that you have a nice function to extract the data, you can apply it to the lines of a data file in a simple loop: with open("255.trim.log") as p: for line in p: if line.startswith("Input "): d = extract(line) print(d) # or process it somehow -- Steven From jenh1536 at gmail.com Tue Apr 14 03:39:36 2015 From: jenh1536 at gmail.com (Janelle Harb) Date: Mon, 13 Apr 2015 21:39:36 -0400 Subject: [Tutor] Python Help Message-ID: Hello! I have a Mac and idle refuses to quit no matter what I try to do. What should I do? Thank you! -Janelle From alan.gauld at btinternet.com Tue Apr 14 09:58:19 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 14 Apr 2015 08:58:19 +0100 Subject: [Tutor] Python Help In-Reply-To: References: Message-ID: On 14/04/15 02:39, Janelle Harb wrote: > Hello! I have a Mac and idle refuses to quit no matter what I try to do. What should I do? You can start by giving us some specific examples of things you did that didn't work. Starting with the obvious: 1) Did you click the little close icon? 2) Did you use the Quit option in the menus? 3) Did you try a Force Quit? 4) Did you run kill from the terminal? 5) Did you try rebooting? 6) Did you hit it with a club hammer? Without any idea of what you did we can't suggest anything specific. It might also help if you tell us which OS version, which Python version, and whether this has always been the case or if its something that only happened recently. If the latter, what were you doing with IDLE immediately before the problem arose? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Tue Apr 14 10:00:47 2015 From: __peter__ at web.de (Peter Otten) Date: Tue, 14 Apr 2015 10:00:47 +0200 Subject: [Tutor] Regular expression on python References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> Message-ID: Steven D'Aprano wrote: > On Mon, Apr 13, 2015 at 02:29:07PM +0200, jarod_v6 at libero.it wrote: >> Dear all. >> I would like to extract from some file some data. >> The line I'm interested is this: >> >> Input Read Pairs: 2127436 Both Surviving: 1795091 (84.38%) Forward >> Only Surviving: 17315 (0.81%) Reverse Only Surviving: 6413 (0.30%) >> Dropped: 308617 (14.51%) > > > Some people, when confronted with a problem, think "I know, I'll > use regular expressions." Now they have two problems. > -- Jamie Zawinski > ? > I swear that Perl has been a blight on an entire generation of > programmers. All they know is regular expressions, so they turn every > data processing problem into a regular expression. Or at least they > *try* to. As you have learned, regular expressions are hard to read, > hard to write, and hard to get correct. > > Let's write some Python code instead. > > > def extract(line): > # Extract key:number values from the string. > line = line.strip() # Remove leading and trailing whitespace. > words = line.split() > accumulator = [] # Collect parts of the string we care about. > for word in words: > if word.startswith('(') and word.endswith('%)'): > # We don't care about percentages in brackets. > continue > try: > n = int(word) > except ValueError: > accumulator.append(word) > else: > accumulator.append(n) > # Now accumulator will be a list of strings and ints: > # e.g. ['Input', 'Read', 'Pairs:', 1234, 'Both', 'Surviving:', 1000] > # Collect consecutive strings as the key, int to be the value. > results = {} > keyparts = [] > for item in accumulator: > if isinstance(item, int): > key = ' '.join(keyparts) > keyparts = [] > if key.endswith(':'): > key = key[:-1] > results[key] = item > else: > keyparts.append(item) > # When we have finished processing, the keyparts list should be empty. > if keyparts: > extra = ' '.join(keyparts) > print('Warning: found extra text at end of line "%s".' % extra) > return results > > > > Now let me test it: > > py> line = ('Input Read Pairs: 2127436 Both Surviving: 1795091' > ... ' (84.38%) Forward Only Surviving: 17315 (0.81%)' > ... ' Reverse Only Surviving: 6413 (0.30%) Dropped:' > ... ' 308617 (14.51%)\n') > py> > py> print(line) > Input Read Pairs: 2127436 Both Surviving: 1795091 (84.38%) Forward > Only Surviving: 17315 (0.81%) Reverse Only Surviving: 6413 (0.30%) > Dropped: 308617 (14.51%) > > py> extract(line) > {'Dropped': 308617, 'Both Surviving': 1795091, 'Reverse Only Surviving': > 6413, 'Forward Only Surviving': 17315, 'Input Read Pairs': 2127436} > > > Remember that dicts are unordered. All the data is there, but in > arbitrary order. Now that you have a nice function to extract the data, > you can apply it to the lines of a data file in a simple loop: > > with open("255.trim.log") as p: > for line in p: > if line.startswith("Input "): > d = extract(line) > print(d) # or process it somehow The tempter took posession of me and dictated: >>> pprint.pprint( ... [(k, int(v)) for k, v in ... re.compile(r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*").findall(line)]) [('Input Read Pairs', 2127436), ('Both Surviving', 1795091), ('Forward Only Surviving', 17315), ('Reverse Only Surviving', 6413), ('Dropped', 308617)] From steve at pearwood.info Tue Apr 14 14:21:25 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 14 Apr 2015 22:21:25 +1000 Subject: [Tutor] Regular expression on python In-Reply-To: References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> Message-ID: <20150414122124.GE5663@ando.pearwood.info> On Tue, Apr 14, 2015 at 10:00:47AM +0200, Peter Otten wrote: > Steven D'Aprano wrote: > > I swear that Perl has been a blight on an entire generation of > > programmers. All they know is regular expressions, so they turn every > > data processing problem into a regular expression. Or at least they > > *try* to. As you have learned, regular expressions are hard to read, > > hard to write, and hard to get correct. > > > > Let's write some Python code instead. [...] > The tempter took posession of me and dictated: > > >>> pprint.pprint( > ... [(k, int(v)) for k, v in > ... re.compile(r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*").findall(line)]) > [('Input Read Pairs', 2127436), > ('Both Surviving', 1795091), > ('Forward Only Surviving', 17315), > ('Reverse Only Surviving', 6413), > ('Dropped', 308617)] Nicely done :-) I didn't say that it *couldn't* be done with a regex. Only that it is harder to read, write, etc. Regexes are good tools, but they aren't the only tool and as a beginner, which would you rather debug? The extract() function I wrote, or r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*" ? Oh, and for the record, your solution is roughly 4-5 times faster than the extract() function on my computer. If I knew the requirements were not likely to change (that is, the maintenance burden was likely to be low), I'd be quite happy to use your regex solution in production code, although I would probably want to write it out in verbose mode just in case the requirements did change: r"""(?x) (?# verbose mode) (.+?): (?# capture one or more character, followed by a colon) \s+ (?# one or more whitespace) (\d+) (?# capture one or more digits) (?: (?# don't capture ... ) \s+ (?# one or more whitespace) \(.*?\) (?# anything inside round brackets) )? (?# ... and optional) \s* (?# ignore trailing spaces) """ That's a hint to people learning regular expressions: start in verbose mode, then "de-verbose" it if you must. -- Steve From __peter__ at web.de Tue Apr 14 16:37:14 2015 From: __peter__ at web.de (Peter Otten) Date: Tue, 14 Apr 2015 16:37:14 +0200 Subject: [Tutor] Regular expression on python References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> Message-ID: Steven D'Aprano wrote: > On Tue, Apr 14, 2015 at 10:00:47AM +0200, Peter Otten wrote: >> Steven D'Aprano wrote: > >> > I swear that Perl has been a blight on an entire generation of >> > programmers. All they know is regular expressions, so they turn every >> > data processing problem into a regular expression. Or at least they >> > *try* to. As you have learned, regular expressions are hard to read, >> > hard to write, and hard to get correct. >> > >> > Let's write some Python code instead. > [...] > >> The tempter took posession of me and dictated: >> >> >>> pprint.pprint( >> ... [(k, int(v)) for k, v in >> ... re.compile(r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*").findall(line)]) >> [('Input Read Pairs', 2127436), >> ('Both Surviving', 1795091), >> ('Forward Only Surviving', 17315), >> ('Reverse Only Surviving', 6413), >> ('Dropped', 308617)] > > Nicely done :-) > > I didn't say that it *couldn't* be done with a regex. I didn't claim that. > Only that it is > harder to read, write, etc. Regexes are good tools, but they aren't the > only tool and as a beginner, which would you rather debug? The extract() > function I wrote, or r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*" ? I know a rhetorical question when I see one ;) > Oh, and for the record, your solution is roughly 4-5 times faster than > the extract() function on my computer. I wouldn't be bothered by that. See below if you are. > If I knew the requirements were > not likely to change (that is, the maintenance burden was likely to be > low), I'd be quite happy to use your regex solution in production code, > although I would probably want to write it out in verbose mode just in > case the requirements did change: > > > r"""(?x) (?# verbose mode) > (.+?): (?# capture one or more character, followed by a colon) > \s+ (?# one or more whitespace) > (\d+) (?# capture one or more digits) > (?: (?# don't capture ... ) > \s+ (?# one or more whitespace) > \(.*?\) (?# anything inside round brackets) > )? (?# ... and optional) > \s* (?# ignore trailing spaces) > """ > > > That's a hint to people learning regular expressions: start in verbose > mode, then "de-verbose" it if you must. Regarding the speed of the Python approach: you can easily improve that by relatively minor modifications. The most important one is to avoid the exception: $ python parse_jarod.py $ python3 parse_jarod.py The regex for reference: $ python3 -m timeit -s "from parse_jarod import extract_re as extract" "extract()" 100000 loops, best of 3: 18.6 usec per loop Steven's original extract(): $ python3 -m timeit -s "from parse_jarod import extract_daprano as extract" "extract()" 10000 loops, best of 3: 92.6 usec per loop Avoid raising ValueError (This won't work with negative numbers): $ python3 -m timeit -s "from parse_jarod import extract_daprano2 as extract" "extract()" 10000 loops, best of 3: 44.3 usec per loop Collapse the two loops into one, thus avoiding the accumulator list and the isinstance() checks: $ python3 -m timeit -s "from parse_jarod import extract_daprano3 as extract" "extract()" 10000 loops, best of 3: 29.6 usec per loop Ok, this is still slower than the regex, a result that I cannot accept. Let's try again: $ python3 -m timeit -s "from parse_jarod import extract_py as extract" "extract()" 100000 loops, best of 3: 15.1 usec per loop Heureka? The "winning" code is brittle and probably as hard to understand as the regex. You can judge for yourself if you're interested: $ cat parse_jarod.py import re line = ("Input Read Pairs: 2127436 " "Both Surviving: 1795091 (84.38%) " "Forward Only Surviving: 17315 (0.81%) " "Reverse Only Surviving: 6413 (0.30%) " "Dropped: 308617 (14.51%)") _findall = re.compile(r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*").findall def extract_daprano(line=line): # Extract key:number values from the string. line = line.strip() # Remove leading and trailing whitespace. words = line.split() accumulator = [] # Collect parts of the string we care about. for word in words: if word.startswith('(') and word.endswith('%)'): # We don't care about percentages in brackets. continue try: n = int(word) except ValueError: accumulator.append(word) else: accumulator.append(n) # Now accumulator will be a list of strings and ints: # e.g. ['Input', 'Read', 'Pairs:', 1234, 'Both', 'Surviving:', 1000] # Collect consecutive strings as the key, int to be the value. results = {} keyparts = [] for item in accumulator: if isinstance(item, int): key = ' '.join(keyparts) keyparts = [] if key.endswith(':'): key = key[:-1] results[key] = item else: keyparts.append(item) # When we have finished processing, the keyparts list should be empty. if keyparts: extra = ' '.join(keyparts) print('Warning: found extra text at end of line "%s".' % extra) return results def extract_daprano2(line=line): words = line.split() accumulator = [] for word in words: if word.startswith('(') and word.endswith('%)'): continue if word.isdigit(): word = int(word) accumulator.append(word) results = {} keyparts = [] for item in accumulator: if isinstance(item, int): key = ' '.join(keyparts) keyparts = [] if key.endswith(':'): key = key[:-1] results[key] = item else: keyparts.append(item) # When we have finished processing, the keyparts list should be empty. if keyparts: extra = ' '.join(keyparts) print('Warning: found extra text at end of line "%s".' % extra) return results def extract_daprano3(line=line): results = {} keyparts = [] for word in line.split(): if word.startswith("("): continue if word.isdigit(): key = ' '.join(keyparts) keyparts = [] if key.endswith(':'): key = key[:-1] results[key] = int(word) else: keyparts.append(word) # When we have finished processing, the keyparts list should be empty. if keyparts: extra = ' '.join(keyparts) print('Warning: found extra text at end of line "%s".' % extra) return results def extract_re(line=line): return {k: int(v) for k, v in _findall(line)} def extract_py(line=line): key = None result = {} for part in line.split(":"): if key is None: key = part else: value, new_key = part.split(None, 1) result[key] = int(value) key = new_key.rpartition(")")[-1].strip() return result if __name__ == "__main__": assert (extract_daprano() == extract_re() == extract_daprano2() == extract_daprano3() == extract_py()) From cybervigilante at gmail.com Tue Apr 14 18:56:32 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Tue, 14 Apr 2015 09:56:32 -0700 Subject: [Tutor] where is the wsgi server root? Message-ID: I set up a simple python wsgi server on port 8000, which works, but where the heck is the server root? Is there a physical server root I can simply put a python program in, as I put a html program into the wampserver root, and see it in a browser on localhost:port 8000, or do I need to do a bit more reading ;') I just cut and pasted the server setup code from the docs, and assumed a server would have a physical root as my local wampserver does. I don't want to fool with django right now - just do the simplest thing to see if I can get python on a web page since I'm used to making them. Or if the root is virtual how do I set up a physical root? Or am I totally confused? -- Jim From alan.gauld at btinternet.com Wed Apr 15 01:09:09 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 15 Apr 2015 00:09:09 +0100 Subject: [Tutor] where is the wsgi server root? In-Reply-To: References: Message-ID: On 14/04/15 17:56, Jim Mooney wrote: > simplest thing to see if I can get python on a web page since I'm used to > making them. > > Or if the root is virtual how do I set up a physical root? I'm guessing; but I'd expect it to be the current directory when you started the server. try adding a print( os,getcwd() ) And see if the result is your root. Or you could try reading the documents...they might tell you! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From joel.goldstick at gmail.com Wed Apr 15 01:23:47 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Tue, 14 Apr 2015 19:23:47 -0400 Subject: [Tutor] where is the wsgi server root? In-Reply-To: References: Message-ID: On Tue, Apr 14, 2015 at 12:56 PM, Jim Mooney wrote: > I set up a simple python wsgi server on port 8000, which works, but where > the heck is the server root? Is there a physical server root I can simply > put a python program in, as I put a html program into the wampserver root, > and see it in a browser on localhost:port 8000, or do I need to do a bit > more reading ;') I just cut and pasted the server setup code from the > docs, and assumed a server would have a physical root as my local > wampserver does. I don't want to fool with django right now - just do the > simplest thing to see if I can get python on a web page since I'm used to > making them. > > Or if the root is virtual how do I set up a physical root? > > Or am I totally confused? > > -- > Jim Here is a link about wsgi: https://code.google.com/p/modwsgi/ It isn't like php. You can put your code anywhere. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From alan.gauld at btinternet.com Wed Apr 15 01:49:26 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 15 Apr 2015 00:49:26 +0100 Subject: [Tutor] Regular expression on python In-Reply-To: <20150414122124.GE5663@ando.pearwood.info> References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> Message-ID: On 14/04/15 13:21, Steven D'Aprano wrote: > although I would probably want to write it out in verbose mode just in > case the requirements did change: > > > r"""(?x) (?# verbose mode) > (.+?): (?# capture one or more character, followed by a colon) > \s+ (?# one or more whitespace) > (\d+) (?# capture one or more digits) > (?: (?# don't capture ... ) > \s+ (?# one or more whitespace) > \(.*?\) (?# anything inside round brackets) > )? (?# ... and optional) > \s* (?# ignore trailing spaces) > """ > > That's a hint to people learning regular expressions: start in verbose > mode, then "de-verbose" it if you must. New one on me. Where does one find out about verbose mode? I don't see it in the re docs? I see an re.X flag but while it seems to be similar in purpose yet it is different to your style above (no parens for example)? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From breamoreboy at yahoo.co.uk Wed Apr 15 01:59:43 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 15 Apr 2015 00:59:43 +0100 Subject: [Tutor] Regular expression on python In-Reply-To: References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> Message-ID: On 15/04/2015 00:49, Alan Gauld wrote: > On 14/04/15 13:21, Steven D'Aprano wrote: > >> although I would probably want to write it out in verbose mode just in >> case the requirements did change: >> >> >> r"""(?x) (?# verbose mode) >> (.+?): (?# capture one or more character, followed by a colon) >> \s+ (?# one or more whitespace) >> (\d+) (?# capture one or more digits) >> (?: (?# don't capture ... ) >> \s+ (?# one or more whitespace) >> \(.*?\) (?# anything inside round brackets) >> )? (?# ... and optional) >> \s* (?# ignore trailing spaces) >> """ >> >> That's a hint to people learning regular expressions: start in verbose >> mode, then "de-verbose" it if you must. > > New one on me. Where does one find out about verbose mode? > I don't see it in the re docs? > > I see an re.X flag but while it seems to be similar in purpose > yet it is different to your style above (no parens for example)? > https://docs.python.org/3/library/re.html#module-contents re.X and re.VERBOSE are together. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From steve at pearwood.info Wed Apr 15 03:02:59 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 15 Apr 2015 11:02:59 +1000 Subject: [Tutor] Regular expression on python In-Reply-To: References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> Message-ID: <20150415010259.GH5663@ando.pearwood.info> On Wed, Apr 15, 2015 at 12:49:26AM +0100, Alan Gauld wrote: > New one on me. Where does one find out about verbose mode? > I don't see it in the re docs? > > I see an re.X flag but while it seems to be similar in purpose > yet it is different to your style above (no parens for example)? I presume it is documented in the main docs, but I actually found this in the "Python Pocket Reference" by Mark Lutz :-) All of the regex flags have three forms: - a numeric flag with a long name; - the same numeric flag with a short name; - a regular expression pattern. So you can either do: re.compile(pattern, flags) or embed the flag in the pattern. The flags that I know of are: (?i) re.I re.IGNORECASE (?L) re.L re.LOCALE (?M) re.M re.MULTILINE (?s) re.S re.DOTALL (?x) re.X re.VERBOSE The flag can appear anywhere in the pattern and applies to the whole pattern, but it is good practice to put them at the front, and in the future it may be an error to put the flags elsewhere. When provided as a separate argument, you can combine flags like this: re.I|re.X -- Steve From akleider at sonic.net Wed Apr 15 07:58:18 2015 From: akleider at sonic.net (Alex Kleider) Date: Tue, 14 Apr 2015 22:58:18 -0700 Subject: [Tutor] Regular expression on python In-Reply-To: References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> Message-ID: On 2015-04-14 16:49, Alan Gauld wrote: > New one on me. Where does one find out about verbose mode? > I don't see it in the re docs? This is where I go whenever I find myself having to (re)learn the details of regex: https://docs.python.org/3/howto/regex.html I believe a '2' can be substituted for the '3' but I've not found any difference between the two. (I submit this not so much for Alan (tutor) as for those like me who are learning.) From cybervigilante at gmail.com Wed Apr 15 05:11:41 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Tue, 14 Apr 2015 20:11:41 -0700 Subject: [Tutor] where is the wsgi server root? In-Reply-To: References: Message-ID: I'm guessing; but I'd expect it to be the current directory > when you started the server. try adding a > > print( os,getcwd() ) > > And see if the result is your root. > Or you could try reading the documents...they might tell you! > > -- > Alan G Read the docs? Where's the fun in that ;') Actually, I found the root in the curdir and got a simple index.html page going on the python server at port 8000. Odd, I figured it would be index.py, as in index.php. That's all I wanted to do at present - see if I could get it working. Jim From alan.gauld at btinternet.com Wed Apr 15 09:19:04 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 15 Apr 2015 08:19:04 +0100 Subject: [Tutor] Regular expression on python In-Reply-To: <20150415010259.GH5663@ando.pearwood.info> References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> <20150415010259.GH5663@ando.pearwood.info> Message-ID: On 15/04/15 02:02, Steven D'Aprano wrote: >> New one on me. Where does one find out about verbose mode? >> I don't see it in the re docs? >> > or embed the flag in the pattern. The flags that I know of are: > > (?x) re.X re.VERBOSE > > The flag can appear anywhere in the pattern and applies to the whole > pattern, but it is good practice to put them at the front, and in the > future it may be an error to put the flags elsewhere. I've always applied flags as separate params at the end of the function call. I've never seen (or noticed?) the embedded form, and don't see it described in the docs anywhere (although it probably is). But the re module descriptions of the flags only goive the re.X/re.VERBOSE options, no mention of the embedded form. Maybe you are just supposed to infer the (?x) form from the re.X... However, that still doesn't explain the difference in your comment syntax. The docs say the verbose syntax looks like: a = re.compile(r"""\d + # the integral part \. # the decimal point \d * # some fractional digits""", re.X) Whereas your syntax is like: a = re.compile(r"""(?x) (?# turn on verbose mode) \d + (?# the integral part) \. (?# the decimal point) \d * (?# some fractional digits)""") Again, where is that described? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Wed Apr 15 10:24:59 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Apr 2015 10:24:59 +0200 Subject: [Tutor] Regular expression on python References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> <20150415010259.GH5663@ando.pearwood.info> Message-ID: Alan Gauld wrote: > On 15/04/15 02:02, Steven D'Aprano wrote: >>> New one on me. Where does one find out about verbose mode? >>> I don't see it in the re docs? >>> > >> or embed the flag in the pattern. The flags that I know of are: >> >> (?x) re.X re.VERBOSE >> >> The flag can appear anywhere in the pattern and applies to the whole >> pattern, but it is good practice to put them at the front, and in the >> future it may be an error to put the flags elsewhere. > > I've always applied flags as separate params at the end of the > function call. I've never seen (or noticed?) the embedded form, > and don't see it described in the docs anywhere (although it > probably is). Quoting : """ (?aiLmsux) (One or more letters from the set 'a', 'i', 'L', 'm', 's', 'u', 'x'.) The group matches the empty string; the letters set the corresponding flags: re.A (ASCII-only matching), re.I (ignore case), re.L (locale dependent), re.M (multi-line), re.S (dot matches all), and re.X (verbose), for the entire regular expression. (The flags are described in Module Contents.) This is useful if you wish to include the flags as part of the regular expression, instead of passing a flag argument to the re.compile() function. Note that the (?x) flag changes how the expression is parsed. It should be used first in the expression string, or after one or more whitespace characters. If there are non-whitespace characters before the flag, the results are undefined. """ > But the re module descriptions of the flags only goive the > re.X/re.VERBOSE options, no mention of the embedded form. > Maybe you are just supposed to infer the (?x) form from the re.X... > > However, that still doesn't explain the difference in your comment > syntax. > > The docs say the verbose syntax looks like: > > a = re.compile(r"""\d + # the integral part > \. # the decimal point > \d * # some fractional digits""", re.X) > > Whereas your syntax is like: > > a = re.compile(r"""(?x) (?# turn on verbose mode) > \d + (?# the integral part) > \. (?# the decimal point) > \d * (?# some fractional digits)""") > > Again, where is that described? """ (?#...) A comment; the contents of the parentheses are simply ignored. """ Let's try it out: >>> re.compile("\d+(?# sequence of digits)").findall("alpha 123 beta 456") ['123', '456'] >>> re.compile("\d+# sequence of digits").findall("alpha 123 beta 456") [] >>> re.compile("\d+# sequence of digits", re.VERBOSE).findall("alpha 123 beta 456") ['123', '456'] So (?#...)-style comments work in non-verbose mode, too, and Steven is wearing belt and braces (almost, the verbose flag is still necessary to ignore the extra whitespace). From fomcl at yahoo.com Wed Apr 15 10:50:04 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 15 Apr 2015 01:50:04 -0700 Subject: [Tutor] Regular expression on python In-Reply-To: Message-ID: <1429087804.16005.YahooMailBasic@web163804.mail.gq1.yahoo.com> -------------------------------------------- On Tue, 4/14/15, Peter Otten <__peter__ at web.de> wrote: Subject: Re: [Tutor] Regular expression on python To: tutor at python.org Date: Tuesday, April 14, 2015, 4:37 PM Steven D'Aprano wrote: > On Tue, Apr 14, 2015 at 10:00:47AM +0200, Peter Otten wrote: >> Steven D'Aprano wrote: > >> > I swear that Perl has been a blight on an entire generation of >> > programmers. All they know is regular expressions, so they turn every >> > data processing problem into a regular expression. Or at least they >> > *try* to. As you have learned, regular expressions are hard to read, >> > hard to write, and hard to get correct. >> > >> > Let's write some Python code instead. > [...] > >> The tempter took posession of me and dictated: >> >> >>> pprint.pprint( >> ... [(k, int(v)) for k, v in >> ... re.compile(r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*").findall(line)]) >> [('Input Read Pairs', 2127436), >>? ('Both Surviving', 1795091), >>? ('Forward Only Surviving', 17315), >>? ('Reverse Only Surviving', 6413), >>? ('Dropped', 308617)] > > Nicely done :-) > Yes, nice, but why do you use re.compile(regex).findall(line) and not re.findall(regex, line) I know what re.compile is for. I often use it outside a loop and then actually use the compiled regex inside a loop, I just haven't see the way you use it before. > I didn't say that it *couldn't* be done with a regex. I didn't claim that. > Only that it is > harder to read, write, etc. Regexes are good tools, but they aren't the > only tool and as a beginner, which would you rather debug? The extract() > function I wrote, or r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*" ? I know a rhetorical question when I see one ;) > Oh, and for the record, your solution is roughly 4-5 times faster than > the extract() function on my computer. I wouldn't be bothered by that. See below if you are. > If I knew the requirements were > not likely to change (that is, the maintenance burden was likely to be > low), I'd be quite happy to use your regex solution in production code, > although I would probably want to write it out in verbose mode just in > case the requirements did change: > > > r"""(?x)? ? (?# verbose mode) personally, I prefer to be verbose about being verbose, ie use the re.VERBOSE flag. But perhaps that's just a matter of taste. Are there any use cases when the ?iLmsux operators are clearly a better choice than the equivalent flag? For me, the mental burden of a regex is big enough already without these operators. >? ???(.+?):? (?# capture one or more character, followed by a colon) >? ???\s+? ???(?# one or more whitespace) >? ???(\d+)???(?# capture one or more digits) >? ???(?:? ???(?# don't capture ... ) >? ? ???\s+? ? ???(?# one or more whitespace) >? ? ???\(.*?\)???(?# anything inside round brackets) >? ? ???)?? ? ? ? (?# ... and optional) >? ???\s*? ???(?# ignore trailing spaces) >? ???""" From __peter__ at web.de Wed Apr 15 11:42:34 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Apr 2015 11:42:34 +0200 Subject: [Tutor] Regular expression on python References: <1429087804.16005.YahooMailBasic@web163804.mail.gq1.yahoo.com> Message-ID: Albert-Jan Roskam wrote: > On Tue, 4/14/15, Peter Otten <__peter__ at web.de> wrote: >>> >>> pprint.pprint( >>> ... [(k, int(v)) for k, v in >>> ... >re.compile(r"(.+?):\s+(\d+)(?:\s+\(.*?\))?\s*").findall(line)]) >>> [('Input Read Pairs', 2127436), >>>('Both Surviving', 1795091), >>>('Forward Only Surviving', 17315), >>>('Reverse Only Surviving', 6413), >>>('Dropped', 308617)] > Yes, nice, but why do you use > re.compile(regex).findall(line) > and not > re.findall(regex, line) > > I know what re.compile is for. I often use it outside a loop and then > actually use the compiled regex inside a loop, I just haven't see the way > you use it before. What you describe here is how I use regular expressions most of the time. Also, re.compile() behaves the same over different Python versions while the shortcuts for the pattern methods changed signature over time. Finally, some have a gotcha. Compare: >>> re.compile("a", re.IGNORECASE).sub("b", "aAAaa") 'bbbbb' >>> re.sub("a", "b", "aAAaa", re.IGNORECASE) 'bAAba' Did you expect that? Congrats for thorough reading of the docs ;) > personally, I prefer to be verbose about being verbose, ie use the > re.VERBOSE flag. But perhaps that's just a matter of taste. Are there any > use cases when the ?iLmsux operators are clearly a better choice than the > equivalent flag? For me, the mental burden of a regex is big enough > already without these operators. I pass flags separately myself, but >>> re.sub("(?i)a", "b", "aAAaa") 'bbbbb' might serve as an argument for inlined flags. From beachkidken at gmail.com Wed Apr 15 14:21:33 2015 From: beachkidken at gmail.com (Ken G.) Date: Wed, 15 Apr 2015 08:21:33 -0400 Subject: [Tutor] Changing a string number to another number Message-ID: <552E57CD.60005@gmail.com> When running the following code, I get the following error code: 201504110102030405061 Traceback (most recent call last): File "Mega_Millions_Tickets_Change.py", line 11, in datecode[20:21] = "0" TypeError: 'str' object does not support item assignment datecode = "201504110102030405061" print datecode if datecode[20:21] == "1": datecode[20:21] = "0" print datecode I have tried using the zero as an integer but still get the same error code. Any suggestion? Thanks in advance, Ken From davea at davea.name Wed Apr 15 14:36:17 2015 From: davea at davea.name (Dave Angel) Date: Wed, 15 Apr 2015 08:36:17 -0400 Subject: [Tutor] Changing a string number to another number In-Reply-To: <552E57CD.60005@gmail.com> References: <552E57CD.60005@gmail.com> Message-ID: <552E5B41.8040009@davea.name> On 04/15/2015 08:21 AM, Ken G. wrote: > When running the following code, I get the following > error code: > > 201504110102030405061 > Traceback (most recent call last): > File "Mega_Millions_Tickets_Change.py", line 11, in > datecode[20:21] = "0" > TypeError: 'str' object does not support item assignment A 'str' object is immutable, which means simply that you cannot modify it in place. All you can do is create a new str object, and rebind your variable to that new one. That means that there are a number of things you cannot do directly to a string. One of them is modifying a slice, as you're trying to do. > > > datecode = "201504110102030405061" > print datecode > if datecode[20:21] == "1": > datecode[20:21] = "0" > print datecode > > I can see that the first part of this is probably a standard datetime, and might suggest you convert it to one, and modify that as needed. But you're so far to the right that I have to figure you're doing some custom encoding. If you just want to replace a single character of a string, you could use the construct: datecode = datecode[:20] + "0" + datecode[21:] If you need something fancier, perhaps you can generalize it. -- DaveA From __peter__ at web.de Wed Apr 15 14:50:57 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Apr 2015 14:50:57 +0200 Subject: [Tutor] Changing a string number to another number References: <552E57CD.60005@gmail.com> Message-ID: Ken G. wrote: > When running the following code, I get the following > error code: > > 201504110102030405061 > Traceback (most recent call last): > File "Mega_Millions_Tickets_Change.py", line 11, in > datecode[20:21] = "0" > TypeError: 'str' object does not support item assignment > > > datecode = "201504110102030405061" > print datecode > if datecode[20:21] == "1": > datecode[20:21] = "0" > print datecode > > > I have tried using the zero as an integer but still get the same error > code. Any suggestion? Strings in Python are "immutable", i. e. you cannot change them once they are created. Instead you have to construct a new string. In the general case you can get the same effect as replacing the character #n of an all-ascii string with >>> s = "01234567890" >>> n = 3 >>> s[:n] + "x" + s[n+1:] '012x4567890' In your case you want to replace the last character, so s[n+1:] is empty >>> s = "201504110102030405061" >>> n = 20 >>> s[n+1:] '' and just >>> s[:n] + "x" '20150411010203040506x' is sufficient. A word of warning: as you are using Python 2 you are actually manipulating bytes not characters when using the default string type. This may have ugly consequences: >>> s = "?hnlich" # I'm using UTF-8 >>> print "ae" + s[1:] ae?hnlich Here the new string is not valid UTF-8 because in that encoding a-umlaut consists of two bytes and I'm only removing one of them. A partial fix is to use unicode explicitly: >>> s = u"?hnlich" >>> print "ae" + s[1:] aehnlich But if you are just starting consider switching to Python 3 where unicode is the default string type. From beachkidken at gmail.com Wed Apr 15 14:51:44 2015 From: beachkidken at gmail.com (Ken G.) Date: Wed, 15 Apr 2015 08:51:44 -0400 Subject: [Tutor] Changing a string number to another number [RESOLVED] In-Reply-To: <552E5B41.8040009@davea.name> References: <552E57CD.60005@gmail.com> <552E5B41.8040009@davea.name> Message-ID: <552E5EE0.1040702@gmail.com> On 04/15/2015 08:36 AM, Dave Angel wrote: > On 04/15/2015 08:21 AM, Ken G. wrote: >> When running the following code, I get the following >> error code: >> >> 201504110102030405061 >> Traceback (most recent call last): >> File "Mega_Millions_Tickets_Change.py", line 11, in >> datecode[20:21] = "0" >> TypeError: 'str' object does not support item assignment > > A 'str' object is immutable, which means simply that you cannot modify > it in place. All you can do is create a new str object, and rebind > your variable to that new one. That means that there are a number of > things you cannot do directly to a string. One of them is modifying a > slice, as you're trying to do. > >> >> >> datecode = "201504110102030405061" >> print datecode >> if datecode[20:21] == "1": >> datecode[20:21] = "0" >> print datecode >> >> > > I can see that the first part of this is probably a standard datetime, > and might suggest you convert it to one, and modify that as needed. > But you're so far to the right that I have to figure you're doing some > custom encoding. > > If you just want to replace a single character of a string, you could > use the construct: > > datecode = datecode[:20] + "0" + datecode[21:] > > If you need something fancier, perhaps you can generalize it. > Thank you, Dave. That did the trick. You were partly right about the datetime as the first part is a date and following contains the lotto numbers purchased for that date of a drawing. The last number in the string indicates if a bonus multiplier for the ticket was purchased, 0 for no and 1 for yes. Again, thanks. Ken From robertvstepp at gmail.com Wed Apr 15 14:55:28 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 15 Apr 2015 07:55:28 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? Message-ID: Solaris 10, Python 2.4.4 I have very little experience with issuing print commands using a Unix environment. Despite this, I wish to design a Tkinter window with a "Print" button, which, when clicked, would create a copy of the contents of the window as a .pdf file. GhostScript is available on my systems. I know that the Canvas container has the ability to print itself to a postscript file, but I do not want to use Canvas as my container object. So I am hopeful this is as simple as discovering the proper command to associate with a button, which will generate a color postscript file of the containing window. Once I can get that file, I know how to get a .pdf out of it. The main software that we use on these systems has this print command associated with its color printer *button*: lp -c -d ricoh -o resolution=1200 -o profile=photo -o dithering=photo -o colorsettings=superfine -o black=k -o papper=letter -o itray=tray1 BTW, "papper" is what is actually in this software product's color printer settings. But can this be correct? Anyway, it does print to *paper*! I suspect that some variant of this command associated with a print button would print *something*, but how do I get it to print the specific window containing the to-be-designed print button? Also, I need it to print a postscript file, not print to paper. I suspect this is another configuration setting that I need to research. As always, many thanks in advance! -- boB From steve at pearwood.info Wed Apr 15 15:09:25 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 15 Apr 2015 23:09:25 +1000 Subject: [Tutor] Changing a string number to another number In-Reply-To: <552E57CD.60005@gmail.com> References: <552E57CD.60005@gmail.com> Message-ID: <20150415130924.GI5663@ando.pearwood.info> On Wed, Apr 15, 2015 at 08:21:33AM -0400, Ken G. wrote: > When running the following code, I get the following > error code: > > 201504110102030405061 > Traceback (most recent call last): > File "Mega_Millions_Tickets_Change.py", line 11, in > datecode[20:21] = "0" > TypeError: 'str' object does not support item assignment Try this: datacode = datacode[:20] + "0" + datacode[21:] This is called "slicing". We take a slice of the string, from the start up to just before position 20; "0"; and a slice from position 21 to the end of the string. The three pieces are then concatenated together, giving a new string. -- Steve From beachkidken at gmail.com Wed Apr 15 15:15:46 2015 From: beachkidken at gmail.com (Ken G.) Date: Wed, 15 Apr 2015 09:15:46 -0400 Subject: [Tutor] Changing a string number to another number [RESOLVED] In-Reply-To: References: <552E57CD.60005@gmail.com> Message-ID: <552E6482.3040701@gmail.com> On 04/15/2015 08:50 AM, Peter Otten wrote: > Ken G. wrote: > >> When running the following code, I get the following >> error code: >> >> 201504110102030405061 >> Traceback (most recent call last): >> File "Mega_Millions_Tickets_Change.py", line 11, in >> datecode[20:21] = "0" >> TypeError: 'str' object does not support item assignment >> >> >> datecode = "201504110102030405061" >> print datecode >> if datecode[20:21] == "1": >> datecode[20:21] = "0" >> print datecode >> >> >> I have tried using the zero as an integer but still get the same error >> code. Any suggestion? > Strings in Python are "immutable", i. e. you cannot change them once they > are created. Instead you have to construct a new string. In the general case > you can get the same effect as replacing the character #n of an all-ascii > string with > >>>> s = "01234567890" >>>> n = 3 >>>> s[:n] + "x" + s[n+1:] > '012x4567890' > > In your case you want to replace the last character, so s[n+1:] is empty > >>>> s = "201504110102030405061" >>>> n = 20 >>>> s[n+1:] > '' > > and just > >>>> s[:n] + "x" > '20150411010203040506x' > > is sufficient. A word of warning: as you are using Python 2 you are actually > manipulating bytes not characters when using the default string type. This > may have ugly consequences: > >>>> s = "?hnlich" # I'm using UTF-8 >>>> print "ae" + s[1:] > ae?hnlich > > Here the new string is not valid UTF-8 because in that encoding a-umlaut > consists of two bytes and I'm only removing one of them. > > A partial fix is to use unicode explicitly: > >>>> s = u"?hnlich" >>>> print "ae" + s[1:] > aehnlich > > But if you are just starting consider switching to Python 3 where unicode is > the default string type. > Thank you, Peter. That would be something for me to consider. Alas, I am still using Python 2.7.6 but do have it on standby. Again, thanks. Ken From beachkidken at gmail.com Wed Apr 15 15:18:59 2015 From: beachkidken at gmail.com (Ken G.) Date: Wed, 15 Apr 2015 09:18:59 -0400 Subject: [Tutor] Changing a string number to another number [RESOLVED] In-Reply-To: <20150415130924.GI5663@ando.pearwood.info> References: <552E57CD.60005@gmail.com> <20150415130924.GI5663@ando.pearwood.info> Message-ID: <552E6543.2040706@gmail.com> On 04/15/2015 09:09 AM, Steven D'Aprano wrote: > On Wed, Apr 15, 2015 at 08:21:33AM -0400, Ken G. wrote: >> When running the following code, I get the following >> error code: >> >> 201504110102030405061 >> Traceback (most recent call last): >> File "Mega_Millions_Tickets_Change.py", line 11, in >> datecode[20:21] = "0" >> TypeError: 'str' object does not support item assignment > Try this: > > datacode = datacode[:20] + "0" + datacode[21:] > > > This is called "slicing". We take a slice of the string, from the start up to just before position 20; "0"; and a slice from position 21 to the end of the string. The three pieces are then concatenated together, giving a new string. Wow! So darn simple with a good explanation. Thanks! Ken From steve at pearwood.info Wed Apr 15 15:29:08 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 15 Apr 2015 23:29:08 +1000 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: Message-ID: <20150415132908.GK5663@ando.pearwood.info> On Wed, Apr 15, 2015 at 07:55:28AM -0500, boB Stepp wrote: > Solaris 10, Python 2.4.4 > > I have very little experience with issuing print commands using a Unix > environment. Despite this, I wish to design a Tkinter window with a > "Print" button, which, when clicked, would create a copy of the > contents of the window as a .pdf file. GhostScript is available on my > systems. > > I know that the Canvas container has the ability to print itself to a > postscript file, but I do not want to use Canvas as my container > object. You will excuse me, I hope, but I'm afraid that comes across as rather foolish: "I want to hammer this nail into this piece of wood. I have a hammer, but I don't want to use a hammer. I would prefer to use a saw, or perhaps a paint brush. How can I do this?" Why don't you want to use a Canvas? That sounds like it will solve your problem. Use a Canvas as the container, give it a button, and have the button send a message to the Canvas saying "Print yourself to PDF file!" If you explain why you don't wish to use a Canvas, perhaps we can suggest a solution that doesn't involve trying to hammer nails with paint brushes. -- Steve From robertvstepp at gmail.com Wed Apr 15 15:37:35 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 15 Apr 2015 08:37:35 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: <20150415132908.GK5663@ando.pearwood.info> References: <20150415132908.GK5663@ando.pearwood.info> Message-ID: On Wed, Apr 15, 2015 at 8:29 AM, Steven D'Aprano wrote: > On Wed, Apr 15, 2015 at 07:55:28AM -0500, boB Stepp wrote: >> Solaris 10, Python 2.4.4 >> >> I have very little experience with issuing print commands using a Unix >> environment. Despite this, I wish to design a Tkinter window with a >> "Print" button, which, when clicked, would create a copy of the >> contents of the window as a .pdf file. GhostScript is available on my >> systems. >> >> I know that the Canvas container has the ability to print itself to a >> postscript file, but I do not want to use Canvas as my container >> object. > > You will excuse me, I hope, but I'm afraid that comes across as rather > foolish: > > "I want to hammer this nail into this piece of wood. I have a hammer, > but I don't want to use a hammer. I would prefer to use a saw, or > perhaps a paint brush. How can I do this?" > > > Why don't you want to use a Canvas? That sounds like it will solve your > problem. Use a Canvas as the container, give it a button, and have the > button send a message to the Canvas saying "Print yourself to PDF > file!" > > If you explain why you don't wish to use a Canvas, perhaps we can > suggest a solution that doesn't involve trying to hammer nails with > paint brushes. Perhaps I am being foolish! But I do have my reasons, which, in this case, is I wanted to take advantage of the pack and grid geometry managers. These two tools seem to make the positioning of the widgets much easier. Unless I am missing something, in a Canvas container I will have to assign pixel coordinates for everything, which sounds like a lot more work! In any event, I *would* like to know how to solve the original problem, creating a print button that will print the contents of its overall container object. -- boB From zachary.ware+pytut at gmail.com Wed Apr 15 15:50:27 2015 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Wed, 15 Apr 2015 08:50:27 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: <20150415132908.GK5663@ando.pearwood.info> Message-ID: On Apr 15, 2015 9:38 AM, "boB Stepp" wrote: > Perhaps I am being foolish! But I do have my reasons, which, in this > case, is I wanted to take advantage of the pack and grid geometry > managers. These two tools seem to make the positioning of the widgets > much easier. Unless I am missing something, in a Canvas container I > will have to assign pixel coordinates for everything, which sounds > like a lot more work! Couldn't you just map a single Frame widget on the canvas, and use the Frame as your "outer" container? -- Zach On a phone From robertvstepp at gmail.com Wed Apr 15 15:58:26 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 15 Apr 2015 08:58:26 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: <20150415132908.GK5663@ando.pearwood.info> Message-ID: On Wed, Apr 15, 2015 at 8:50 AM, Zachary Ware wrote: > > On Apr 15, 2015 9:38 AM, "boB Stepp" wrote: >> Perhaps I am being foolish! But I do have my reasons, which, in this >> case, is I wanted to take advantage of the pack and grid geometry >> managers. These two tools seem to make the positioning of the widgets >> much easier. Unless I am missing something, in a Canvas container I >> will have to assign pixel coordinates for everything, which sounds >> like a lot more work! > > Couldn't you just map a single Frame widget on the canvas, and use the Frame > as your "outer" container? You are SMART, I am NOT! That sounds like a great idea!! Is this the intent of the Tkinter design to provide print functionality? To always start with a Canvas container? -- boB From __peter__ at web.de Wed Apr 15 17:39:53 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 15 Apr 2015 17:39:53 +0200 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? References: Message-ID: boB Stepp wrote: > Solaris 10, Python 2.4.4 > > I have very little experience with issuing print commands using a Unix > environment. Despite this, I wish to design a Tkinter window with a > "Print" button, which, when clicked, would create a copy of the > contents of the window as a .pdf file. GhostScript is available on my > systems. > > I know that the Canvas container has the ability to print itself to a > postscript file, but I do not want to use Canvas as my container > object. So I am hopeful this is as simple as discovering the proper > command to associate with a button, which will generate a color > postscript file of the containing window. Once I can get that file, I > know how to get a .pdf out of it. > > The main software that we use on these systems has this print command > associated with its color printer *button*: > > lp -c -d ricoh -o resolution=1200 -o profile=photo -o dithering=photo > -o colorsettings=superfine -o black=k -o papper=letter -o itray=tray1 > > BTW, "papper" is what is actually in this software product's color > printer settings. But can this be correct? Anyway, it does print to > *paper*! > > I suspect that some variant of this command associated with a print > button would print *something*, but how do I get it to print the > specific window containing the to-be-designed print button? Also, I > need it to print a postscript file, not print to paper. I suspect this > is another configuration setting that I need to research. > > As always, many thanks in advance! I'm on linux and surprisingly subprocess.call(["import", "-window", window_title, postscript_file]) worked. I admit it's a roundabout way... Here's the complete experiment; I ran it with Python 2.7, but that shouldn't make a difference. import Tkinter as tk import subprocess window_title = "gewizzede" postscript_file = "tmp_snapshot.ps" def print_canvas(): # canvas.postscript(file="tmp.ps") subprocess.call(["import", "-window", window_title, postscript_file]) root = tk.Tk() root.title(window_title) canvas = tk.Canvas(root, width=200, height=200) canvas.pack() button = tk.Button(root, text="Print", command=print_canvas) button.pack() demo = tk.Button(root, text = "demo widget button") canvas.create_window(50, 50, window=demo) canvas.create_rectangle(25, 25, 75, 150, fill="red") root.mainloop() You might guess from the above that I tried Zachary's suggestion first, but that printed only the red rectangle, not the demo button. From zachary.ware at gmail.com Wed Apr 15 16:04:58 2015 From: zachary.ware at gmail.com (Zachary Ware) Date: Wed, 15 Apr 2015 09:04:58 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: <20150415132908.GK5663@ando.pearwood.info> Message-ID: On Apr 15, 2015 9:59 AM, "boB Stepp" wrote: > > On Wed, Apr 15, 2015 at 8:50 AM, Zachary Ware > wrote: > > > > On Apr 15, 2015 9:38 AM, "boB Stepp" wrote: > >> Perhaps I am being foolish! But I do have my reasons, which, in this > >> case, is I wanted to take advantage of the pack and grid geometry > >> managers. These two tools seem to make the positioning of the widgets > >> much easier. Unless I am missing something, in a Canvas container I > >> will have to assign pixel coordinates for everything, which sounds > >> like a lot more work! > > > > Couldn't you just map a single Frame widget on the canvas, and use the Frame > > as your "outer" container? > > You are SMART, I am NOT! That sounds like a great idea!! To almost quote Jacob Kaplan-Moss from his keynote talk at PyCon this year, "Hi, I'm [Zach], and I'm a mediocre programmer" :) > Is this the intent of the Tkinter design to provide print > functionality? To always start with a Canvas container? I honestly have no idea. -- Zach On a phone From alan.gauld at btinternet.com Wed Apr 15 17:57:49 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 15 Apr 2015 16:57:49 +0100 Subject: [Tutor] Regular expression on python In-Reply-To: References: <2056323956.1540771428928147594.JavaMail.httpd@webmail-58.iol.local> <20150414014816.GC5663@ando.pearwood.info> <20150414122124.GE5663@ando.pearwood.info> <20150415010259.GH5663@ando.pearwood.info> Message-ID: On 15/04/15 09:24, Peter Otten wrote: >> function call. I've never seen (or noticed?) the embedded form, >> and don't see it described in the docs anywhere > > Quoting : > > """ > (?aiLmsux) > (One or more letters from the set 'a', 'i', 'L', 'm', 's', 'u', 'x'.) The > group matches the empty string; the letters set the corresponding flags: Aha. The trick is knowing the correct search string... I tried 'flag' and 'verbose' but missed this entry. >> Again, where is that described? > > """ > (?#...) > A comment; the contents of the parentheses are simply ignored. > """ OK, I missed that too. Maybe I just wasn't awake enough this morning! :-) Thanks Peter. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Wed Apr 15 18:13:40 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 15 Apr 2015 17:13:40 +0100 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: Message-ID: On 15/04/15 13:55, boB Stepp wrote: > Solaris 10, Python 2.4.4 > > I have very little experience with issuing print commands using a Unix > environment. Despite this, I wish to design a Tkinter window with a > "Print" button, which, when clicked, would create a copy of the > contents of the window as a .pdf file. GhostScript is available on my > systems. Your problem is that Tkinter does not really support the concept of printing to hard copy. Other GUI frameworks (like WxPython) do this much better. So anything you do will be a bit of a kluge. There are some valid reasons for this: printing is extremely OS dependant. And Tk as a cross OS platform doesn't want to have to deal with all the complexity(*). The usual solution is to render the output in some print friendly file format (html, groff, SVG etc) and then send that to the appropriate print command. However if you really want a screen image you might be better invoking one of the many screen capture programs and then printing its output? (*) The main culprits are - Windows which uses a "Device Context" to render its UI. The device can be either a screen or a printer (or notionally anything else) so in theory you just swap the DC and send the GUI to the new device. In practice its not that easy. - MacOSX uses a Cocoa framework which, in turn, uses OpenGL primitives to render the UI and like Windows can theoretically render the UI on non screen devices, It can also render it as PDF natively which is how it normally prints screen images. - *nix usually relies on rendering the output *content* on a new device or in a new format. Printing screenshots in generic Unix is a bit of an afterthought IMHO...Possibly a consequence of X having been designed before the days of affordable colour printers - the same reason Steve Jobs didn't bother with colour on the early Macs - if you couldn't print it, there was no point, he thought... Printing UI images and WYSIWYG type output is one of the few triggers that drive me to WxPython. It handles it much more easily than Tk. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Wed Apr 15 19:00:43 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 15 Apr 2015 12:00:43 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: Message-ID: On Wed, Apr 15, 2015 at 10:39 AM, Peter Otten <__peter__ at web.de> wrote: > boB Stepp wrote: > >> Solaris 10, Python 2.4.4 [...] > > I'm on linux and surprisingly > > subprocess.call(["import", "-window", window_title, postscript_file]) > > worked. I admit it's a roundabout way... I did not find the "import" command in my Unix reference, but found it in the man pages on my Solaris workstation. It looks like this should work without having to use the Canvas container, which was what I was originally asking about. > Here's the complete experiment; I ran it with Python 2.7, but that shouldn't > make a difference. Yes, it ran fine on Python 2.4.4. > import Tkinter as tk Question: I have been using "from Tkinter import *" as suggested in "Programming Python" by Lutz. He remarks that unlike other situations, this is generally safe with Tkinter. Is there a benefit to doing the import as you have? > import subprocess > > window_title = "gewizzede" > postscript_file = "tmp_snapshot.ps" > > def print_canvas(): > # canvas.postscript(file="tmp.ps") > subprocess.call(["import", "-window", window_title, postscript_file]) At first I thought you had a typo here, but now I understand that "# canvas.postscript(file="tmp.ps")" only gave you the window framework. When I made my attempt to employ Zach's suggestion by embedding my existing frames within a Canvas, I only got an empty white rectangle. After searching online for that, I found references that Canvas' postscript method only works for objects drawn on its canvas, NOT embedded windows, frames, etc. This had me scratching my head again. But then your post came in. I am very grateful for your solution! > root = tk.Tk() > root.title(window_title) > > canvas = tk.Canvas(root, width=200, height=200) > canvas.pack() > > button = tk.Button(root, text="Print", command=print_canvas) > button.pack() > > demo = tk.Button(root, text = "demo widget button") > canvas.create_window(50, 50, window=demo) > canvas.create_rectangle(25, 25, 75, 150, fill="red") > root.mainloop() > > You might guess from the above that I tried Zachary's suggestion first, but > that printed only the red rectangle, not the demo button. -- boB From robertvstepp at gmail.com Wed Apr 15 19:07:46 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 15 Apr 2015 12:07:46 -0500 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: Message-ID: On Wed, Apr 15, 2015 at 11:13 AM, Alan Gauld wrote: [...] > Your problem is that Tkinter does not really support the concept > of printing to hard copy. Other GUI frameworks (like WxPython) > do this much better. So anything you do will be a bit of a kluge. > There are some valid reasons for this: printing is extremely OS dependant. > And Tk as a cross OS platform doesn't want to have > to deal with all the complexity(*). This is sounding like developing a platform-independent program involving Tkinter and requiring printing is no easy task. Fortunately my efforts need only run successfully on the Solaris 10 OS. [...] > Printing UI images and WYSIWYG type output is one of the few triggers that > drive me to WxPython. It handles it much more easily than Tk. I will have to keep wxPython in mind. It does not help me at work, but for non-work projects it might be very useful. However, I should work on mastering Tkinter first, as I am sure that all of the principles I learn here will be generically useful for any GUI programming. Thanks, Alan! -- boB From alan.gauld at btinternet.com Wed Apr 15 20:42:20 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 15 Apr 2015 19:42:20 +0100 Subject: [Tutor] How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: Message-ID: On 15/04/15 18:00, boB Stepp wrote: >> import Tkinter as tk > > Question: I have been using "from Tkinter import *" as suggested in > "Programming Python" by Lutz. He remarks that unlike other situations, > this is generally safe with Tkinter. Is there a benefit to doing the > import as you have? Biggest benefit is if you ever move to Python 3 you cansimply change that line to import tkinter as tk and it carries on working (or at least until you hit some of the other renamed modules!) But also if you ever get to use Tix, because it is a superset of Tkinter so you can just change to import tix as tk and it keeps working but you now have access to all the Tix widgets too. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From beachkidken at gmail.com Thu Apr 16 01:47:14 2015 From: beachkidken at gmail.com (Ken G.) Date: Wed, 15 Apr 2015 19:47:14 -0400 Subject: [Tutor] Reference last email message... Message-ID: <552EF882.6050606@gmail.com> I just emailed that I was unable to correct a message in ModTools so I went to Yahoo and made the change and then approved it. Noticing it did not appear on the list, I checked the Activity Log in Yahoo and it was marked Bounced! Several days ago, we had another message correction and that too, bounced. Ken, FreecycleLouisville, KY, USA From alan.gauld at btinternet.com Thu Apr 16 02:21:26 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 16 Apr 2015 01:21:26 +0100 Subject: [Tutor] Reference last email message... In-Reply-To: <552EF882.6050606@gmail.com> References: <552EF882.6050606@gmail.com> Message-ID: On 16/04/15 00:47, Ken G. wrote: > I just emailed that I was unable to correct a message in ModTools > so I went to Yahoo and made the change and then approved it. What is ModTools? What kind of message? Where does Yahoo fit in? What does any of it have to do with this list? I'm confused. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Thu Apr 16 02:45:15 2015 From: davea at davea.name (Dave Angel) Date: Wed, 15 Apr 2015 20:45:15 -0400 Subject: [Tutor] Reference last email message... In-Reply-To: <552EF882.6050606@gmail.com> References: <552EF882.6050606@gmail.com> Message-ID: <552F061B.9040804@davea.name> On 04/15/2015 07:47 PM, Ken G. wrote: > I just emailed that I was unable to correct a message in ModTools > so I went to Yahoo and made the change and then approved it. > > Noticing it did not appear on the list, I checked the Activity Log > in Yahoo and it was marked Bounced! > > Several days ago, we had another message correction and that > too, bounced. > It's conceivable that you're referring to: https://pypi.python.org/pypi/modtools/1.0.2 But your message is so garbled that I have no idea how to respond. You have a gmail address, but you're somehow involved with yahoo. You refer to "the list," but never say if it's this one. You refer to "message correction" but there's no standard way to modify a message on python-tutor once it's mailed or posted. So perhaps the message correction and the list you're referring to are somewhere else. Python-tutor is a limited mailing list that only takes messages from those who have subscribed/joined. So perhaps you have two different email addresses and you've registered using gmail, and are trying to post using yahoo. In any case, if it is ModTools, this is the wrong list to post questions. This list is intended for usage of the Python language and the standard library, and while other subjects are permissible, they're not as likely to get good responses. I'd suggest you email to python-list at python.org a new message, starting a new thread. Be explicit about your question, supplying a URL when you refer to a 3rd party package, and giving python version and OS version. Then show exactly what you've tried and what the result was, posting a full traceback if you got an exception. -- DaveA From __peter__ at web.de Thu Apr 16 09:54:03 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 16 Apr 2015 09:54:03 +0200 Subject: [Tutor] Star imports, was Re: How to get a Tkinter window to print a color copy of itself as a .pdf file? References: Message-ID: boB Stepp wrote: >> import Tkinter as tk > > Question: I have been using "from Tkinter import *" as suggested in > "Programming Python" by Lutz. He remarks that unlike other situations, > this is generally safe with Tkinter. Is there a benefit to doing the > import as you have? It's a stylistic preference: I like to keep namespaces separate. When I make an exception, typically for generic functionality like contextmanager, groupby, namedtuple, defaultdict... I import these in a controlled way with from collections import defaultdict from itertools import islice, zip_longest etc., use them as "pseudo-builtins", and avoid writing functions with the same name myself. By contrast I have no clear idea of what's in the tkinter package and might write my own getint() function, say, thus forcing a reader to scan the complete module to learn which getint() is used. This is a general problem of star imports; when you overwrite an imported name you typically don't care or even know about that name in the imported module. When you read your module later to fix or amend something your knowledge may have grown, and you expect the imported function where the custom function is used. This confusion becomes even more likely when a second developer is involved. From cybervigilante at gmail.com Thu Apr 16 07:03:59 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Wed, 15 Apr 2015 22:03:59 -0700 Subject: [Tutor] Fraction - differing interpretations for number and string Message-ID: Why does Fraction interpret a number and string so differently? They come out the same, but it seems rather odd >>> from fractions import Fraction >>> Fraction(1.64) Fraction(7385903388887613, 4503599627370496) >>> Fraction("1.64") Fraction(41, 25) >>> 41/25 1.64 >>> 7385903388887613 / 4503599627370496 1.64 -- Jim "Greetings, Windows user. Your installation of Linux has been blocked. You are our bitch forever, HaHaHaHaHa!" --signed, your friends at Microsoft From danny.yoo at gmail.com Thu Apr 16 10:52:51 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Thu, 16 Apr 2015 01:52:51 -0700 Subject: [Tutor] Fraction - differing interpretations for number and string In-Reply-To: References: Message-ID: On Apr 16, 2015 1:32 AM, "Jim Mooney" wrote: > > Why does Fraction interpret a number and string so differently? They come > out the same, but it seems rather odd > > >>> from fractions import Fraction > >>> Fraction(1.64) > Fraction(7385903388887613, 4503599627370496) > >>> Fraction("1.64") > Fraction(41, 25) > >>> 41/25 > 1.64 > >>> 7385903388887613 / 4503599627370496 > 1.64 In many systems, if everything is the same shape, then certain operations might be implemented more quickly by making uniform assumptions. If all my clothes were the same, for example, maybe I'd be able to sorry my laundry more quickly. And if all my Tupperware were the same size, then maybe my cabinets wouldn't be the nest of ill fitting plastic that it is now. And if every number was represented with a fixed quantity of bits in a computer, then maybe computer arithmetic could go really fast. It's this last supposition that should be treated most seriously. Most computers use "floating point", a representation of numbers that use a fixed set of bits. This uniformity allows floating point math to be implemented quickly. But it also means that it's inaccurate. You're seeing evidence of the inaccuracy. Read: https://docs.python.org/2/tutorial/floatingpoint.html and see if that helps clarify. From wolfgang.maier at biologie.uni-freiburg.de Thu Apr 16 10:51:50 2015 From: wolfgang.maier at biologie.uni-freiburg.de (Wolfgang Maier) Date: Thu, 16 Apr 2015 10:51:50 +0200 Subject: [Tutor] Fraction - differing interpretations for number and string In-Reply-To: References: Message-ID: On 04/16/2015 07:03 AM, Jim Mooney wrote: > Why does Fraction interpret a number and string so differently? They come > out the same, but it seems rather odd > >>>> from fractions import Fraction >>>> Fraction(1.64) > Fraction(7385903388887613, 4503599627370496) >>>> Fraction("1.64") > Fraction(41, 25) >>>> 41/25 > 1.64 >>>> 7385903388887613 / 4503599627370496 > 1.64 > That is because 1.64 cannot be represented exactly as a float. Try: >>> x = 1.64 >>> format(x,'.60f') '1.639999999999999902300373832986224442720413208007812500000000' If you construct a Fraction from a str OTOH, Fraction assumes you meant exactly that number. And in fact: >>> Fraction('1.639999999999999902300373832986224442720413208007812500000000') Fraction(7385903388887613, 4503599627370496) see also https://docs.python.org/3/tutorial/floatingpoint.html for an explanation of floating-point inaccuracies. From danny.yoo at gmail.com Thu Apr 16 10:55:06 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Thu, 16 Apr 2015 01:55:06 -0700 Subject: [Tutor] Fraction - differing interpretations for number and string In-Reply-To: References: Message-ID: On Apr 16, 2015 1:52 AM, "Danny Yoo" wrote: > > > On Apr 16, 2015 1:32 AM, "Jim Mooney" wrote: > > > > Why does Fraction interpret a number and string so differently? They come > > out the same, but it seems rather odd > > > > >>> from fractions import Fraction > > >>> Fraction(1.64) > > Fraction(7385903388887613, 4503599627370496) > > >>> Fraction("1.64") > > Fraction(41, 25) > > >>> 41/25 > > 1.64 > > >>> 7385903388887613 / 4503599627370496 > > 1.64 > > In many systems, if everything is the same shape, then certain operations might be implemented more quickly by making uniform assumptions. If all my clothes were the same, for example, maybe I'd be able to sorry my laundry more quickly. And if all my Tupperware were the same size, then maybe my cabinets wouldn't be the nest of ill fitting plastic that it is now. Substitute "sorry" with "sort". Sorry! :p From beachkidken at gmail.com Thu Apr 16 14:03:03 2015 From: beachkidken at gmail.com (Ken G.) Date: Thu, 16 Apr 2015 08:03:03 -0400 Subject: [Tutor] Reference last email message... In-Reply-To: <552F061B.9040804@davea.name> References: <552EF882.6050606@gmail.com> <552F061B.9040804@davea.name> Message-ID: <552FA4F7.3080203@gmail.com> On 04/15/2015 08:45 PM, Dave Angel wrote: > On 04/15/2015 07:47 PM, Ken G. wrote: >> I just emailed that I was unable to correct a message in ModTools >> so I went to Yahoo and made the change and then approved it. >> >> Noticing it did not appear on the list, I checked the Activity Log >> in Yahoo and it was marked Bounced! >> >> Several days ago, we had another message correction and that >> too, bounced. >> > > It's conceivable that you're referring to: > > https://pypi.python.org/pypi/modtools/1.0.2 > > But your message is so garbled that I have no idea how to respond. > > You have a gmail address, but you're somehow involved with yahoo. > > You refer to "the list," but never say if it's this one. > > You refer to "message correction" but there's no standard way to > modify a message on python-tutor once it's mailed or posted. So > perhaps the message correction and the list you're referring to are > somewhere else. > > Python-tutor is a limited mailing list that only takes messages from > those who have subscribed/joined. So perhaps you have two different > email addresses and you've registered using gmail, and are trying to > post using yahoo. > > In any case, if it is ModTools, this is the wrong list to post > questions. This list is intended for usage of the Python language and > the standard library, and while other subjects are permissible, > they're not as likely to get good responses. > > I'd suggest you email to python-list at python.org a new message, > starting a new thread. Be explicit about your question, supplying a > URL when you refer to a 3rd party package, and giving python version > and OS version. Then show exactly what you've tried and what the > result was, posting a full traceback if you got an exception. > Oh my! I send this to the wrong address. My apology. < redfaced > Ken From beachkidken at gmail.com Thu Apr 16 14:04:09 2015 From: beachkidken at gmail.com (Ken G.) Date: Thu, 16 Apr 2015 08:04:09 -0400 Subject: [Tutor] Reference last email message... In-Reply-To: References: <552EF882.6050606@gmail.com> Message-ID: <552FA539.2020204@gmail.com> On 04/15/2015 08:21 PM, Alan Gauld wrote: > On 16/04/15 00:47, Ken G. wrote: >> I just emailed that I was unable to correct a message in ModTools >> so I went to Yahoo and made the change and then approved it. > > What is ModTools? What kind of message? > Where does Yahoo fit in? > > What does any of it have to do with this list? > > I'm confused. > Again, my apology. Sent to the wrong address. < redfaced > Ken From davea at davea.name Thu Apr 16 14:11:05 2015 From: davea at davea.name (Dave Angel) Date: Thu, 16 Apr 2015 08:11:05 -0400 Subject: [Tutor] Fraction - differing interpretations for number and string In-Reply-To: References: Message-ID: <552FA6D9.8010907@davea.name> On 04/16/2015 01:03 AM, Jim Mooney wrote: > Why does Fraction interpret a number and string so differently? They come > out the same, but it seems rather odd > >>>> from fractions import Fraction >>>> Fraction(1.64) > Fraction(7385903388887613, 4503599627370496) >>>> Fraction("1.64") > Fraction(41, 25) >>>> 41/25 > 1.64 >>>> 7385903388887613 / 4503599627370496 > 1.64 > When a number isn't an exact integer (and sometimes when the integer is large enough), some common computer number formats cannot store the number exactly. Naturally we know about transcendentals, which cannot be stored exactly in any base. PI and E and the square-root of two are three well known examples. But even rational numbers cannot be stored exactly unless they happen to match the base you're using to store them. For example, 1/3 cannot be stored exactly in any common base. In decimal, it'd be a repeating set of 3's. And whenever you stopped putting down threes, you've made an approximation. 0.3333333333 Python defaults to using a float type, which is a binary floating point representation that uses the special hardware available in most recent computers. And in fact, when you use a literal number in your source, it's converted to a float by the compiler, not stored as the digits you typed. The number you specified in decimal, 1.64, is never going to be stored in a finite number of binary bits, in a float. >>> from fractions import Fraction >>> from decimal import Decimal >>> y = 1.64 Conversion to float appens at compile time, so the value given to y is already approximate. roughly equivalent to the following >>> y = float("1.64") >>> Fraction(y) Fraction(7385903388887613, 4503599627370496) If you converted it in string form instead to Decimal, then the number you entered would be saved exactly. >>> x = Decimal("1.64") This value is stored exactly. >>> x Decimal('1.64') >>> Fraction(x) Fraction(41, 25) Sometimes it's convenient to do the conversion in our head, as it were. Since 1.64 is shorthand for 164/100, we can just pass those integers to Fraction, and get an exact answer again. >>> Fraction(164, 100) Fraction(41, 25) Nothing about this says that Decimal is necessarily better than float. It appears better because we enter values in decimal form and to use float, those have to be converted, and there's frequently a loss during conversion. But Decimal is slower and takes more space, so most current languages use binary floating point instead. I implemented the math on a machine 40 years ago where all user arithmetic was done in decimal floating point. i thought it was a good idea at the time because of a principle I called "least surprise." There were roundoff errors, but only in places where you'd get the same ones doing it by hand. History has decided differently. When the IEEE committee first met, Intel already had its 8087 implemented, and many decisions were based on what that chip could do and couldn't do. So that standard became the default standard that future implementations would use, whatever company. -- DaveA From davea at davea.name Thu Apr 16 14:15:40 2015 From: davea at davea.name (Dave Angel) Date: Thu, 16 Apr 2015 08:15:40 -0400 Subject: [Tutor] Fraction - differing interpretations for number and string In-Reply-To: <552FA6D9.8010907@davea.name> References: <552FA6D9.8010907@davea.name> Message-ID: <552FA7EC.2020904@davea.name> On 04/16/2015 08:11 AM, Dave Angel wrote: > On 04/16/2015 01:03 AM, Jim Mooney wrote: >> Why does Fraction interpret a number and string so differently? They come >> out the same, but it seems rather odd >> >>>>> from fractions import Fraction >>>>> Fraction(1.64) >> Fraction(7385903388887613, 4503599627370496) >>>>> Fraction("1.64") >> Fraction(41, 25) >>>>> 41/25 >> 1.64 >>>>> 7385903388887613 / 4503599627370496 >> 1.64 >> > > When a number isn't an exact integer (and sometimes when the integer is > large enough), some common computer number formats cannot store the > number exactly. Naturally we know about transcendentals, which cannot > be stored exactly in any base. PI and E and the square-root of two are > three well known examples. > > But even rational numbers cannot be stored exactly unless they happen to > match the base you're using to store them. For example, 1/3 cannot be > stored exactly in any common base. By "common" I mean 2, 8, 10, or 16. Obviously if someone implemented a base 3 floating point package, the number would be simply 0.1 > In decimal, it'd be a repeating set > of 3's. And whenever you stopped putting down threes, you've made an > approximation. > 0.3333333333 > > Python defaults to using a float type, which is a binary floating point > representation that uses the special hardware available in most recent > computers. And in fact, when you use a literal number in your source, > it's converted to a float by the compiler, not stored as the digits you > typed. > > The number you specified in decimal, 1.64, is never going to be stored > in a finite number of binary bits, in a float. > > >>> from fractions import Fraction > >>> from decimal import Decimal > > >>> y = 1.64 > Conversion to float appens at compile time, so the value given to y is > already approximate. > roughly equivalent to the following > >>> y = float("1.64") > > >>> Fraction(y) > Fraction(7385903388887613, 4503599627370496) > > If you converted it in string form instead to Decimal, then the number > you entered would be saved exactly. > > >>> x = Decimal("1.64") > This value is stored exactly. > > >>> x > Decimal('1.64') > > >>> Fraction(x) > Fraction(41, 25) > > > Sometimes it's convenient to do the conversion in our head, as it were. > Since 1.64 is shorthand for 164/100, we can just pass those integers to > Fraction, and get an exact answer again. > > >>> Fraction(164, 100) > Fraction(41, 25) > > > Nothing about this says that Decimal is necessarily better than float. > It appears better because we enter values in decimal form and to use > float, those have to be converted, and there's frequently a loss during > conversion. But Decimal is slower and takes more space, so most current > languages use binary floating point instead. > > I implemented the math on a machine 40 years ago where all user > arithmetic was done in decimal floating point. i thought it was a good > idea at the time because of a principle I called "least surprise." There > were roundoff errors, but only in places where you'd get the same ones > doing it by hand. > > History has decided differently. When the IEEE committee first met, > Intel already had its 8087 implemented, and many decisions were based on > what that chip could do and couldn't do. So that standard became the > default standard that future implementations would use, whatever company. > -- DaveA From adeadmarshal at gmail.com Thu Apr 16 12:00:29 2015 From: adeadmarshal at gmail.com (Ali Moradi) Date: Thu, 16 Apr 2015 14:30:29 +0430 Subject: [Tutor] making a list in Tkinter with clickable items (Python 2.x) Message-ID: Hi, i want to load a bunch of words from my database into the listbox in Tkinter, make them clickable, and when i clicked on them the specific meaning of that word apears in a textbox beside the listbox. i have a code but it's not complete. i'm a beginner in Python :( code: #!/bin/python from tkinter import * from tkinter import ttk def z(): global entry if(lb.get(lb.curselection())): txt.insert(END, lb.get(lb.curselection())) root = Tk() entry = ttk.Entry(root);entry.grid(row = 0, column = 0) lb = Listbox(root) a=lb.insert(1, "crime") b=lb.insert(2, "murder") lb.insert(3, "get") lb.insert(4, "take") Button(root, text="BUtt", command=z).grid() lb.grid(row = 1, column = 0) scroll = Scrollbar(root, orient = VERTICAL, command = lb.yview) scroll.grid(row = 0, column = 1, sticky = 'ns') lb.config(yscrollcommand = scroll.set) txt = Text(root, width = 60, height = 30,) txt.grid(row = 1, column = 2) root.mainloop() ----------------------------------- thanks. From steve at pearwood.info Thu Apr 16 15:51:42 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 16 Apr 2015 23:51:42 +1000 Subject: [Tutor] Fraction - differing interpretations for number and string In-Reply-To: References: Message-ID: <20150416135141.GP5663@ando.pearwood.info> On Thu, Apr 16, 2015 at 01:52:51AM -0700, Danny Yoo wrote: > It's this last supposition that should be treated most seriously. Most > computers use "floating point", a representation of numbers that use a > fixed set of bits. This uniformity allows floating point math to be > implemented quickly. But it also means that it's inaccurate. You're > seeing evidence of the inaccuracy. Hmmm. I wouldn't describe it as "inaccurate". The situation is a lot more subtle and complicated than mere inaccuracy, especially these days. Back when dinosaurs ruled the earth, it would be accurate to describe floating point arithmetic as "inaccurate", pun intended. Some of the biggest companies in computing back in the 1970s had floating point arithmetic which was horrible. I'm aware of at least one system where code like this: if x != 0: print 1/x could crash with a Divide By Zero error. And worse! But since IEEE-754 floating point semantics has become almost universal, the situation is quite different. IEEE-754 guarantees that the four basic arithmetic operations + - * / will give the closest possible result to the exact mathematical result, depending on the rounding mode and available precision. If an IEEE-754 floating point system gives a result for some operation like 1/x, you can be sure that this result is the closest you can possibly get to the true mathematical result -- and is often exact. The subtlety is that the numbers you type in decimal are not always the numbers the floating point system is actually dealing with, because they cannot be. What you get though, is the number closest possible to what you want. Let me explain with an analogy. We all know that the decimal for 1/3 is 0.33333-repeating, with an infinite number of threes after the decimal point. That means any decimal number you can possibly write down is not 1/3 exactly, it will either be a tiny bit less, or a tiny bit more. 0.333333333 # pretty close 0.33333333333 # even closer 0.3333333333333 # closer, but still not exact 0.3333333333334 # too big There is no way to write 1/3 exactly as a decimal, and no way to calculate it exactly as a decimal either. If you ask for 1/3 you will get something either a tiny bit smaller than 1/3 or a tiny bit bigger. Computer floating point numbers generally use base 2, not base 10. That means that fractions like 1/2, 1/4, 1/8 and similar can be represented exactly (up to the limit of available precision) but many decimal numbers are like 1/3 in decimal and have an infinitely repeating binary form. Since we don't have an infinite amount of memory, we cannot represent them *exactly* as binary floats. So the decimal fraction 0.5 means 5/10 or if you prefer, (5 * 1/10). That is the same as "1/2" or (1 * 1/2), which means that in base-2 we can write it as "0.1". 0.75 in decimal means (7 * 1/10 + 5 * 1/100). With a bit of simple arithmetic, you should be able to work out that 0.75 is also equal to (1/2 + 1/4), or to put it another way, (1 * 1/2 + 1 * 1/4) which can be written as "0.11" in base-2. But the simple decimal number 0.1 cannot be written in an exact base-2 form: 1/10 is smaller than 1/2, so base-2 "0.1" is too big; 1/10 is smaller than 1/4, so base-2 "0.01" is too big; 1/10 is smaller than 1/8, so base-2 "0.001" is too big; 1/10 is bigger than 1/16, so base-2 "0.0001" is too small; 1/10 is bigger than 1/16 + 1/32, so base-2 "0.00011" is too small; 1/10 is smaller than 1/16 + 1/32 + 1/64, so base-2 "0.000111" is too big; likewise base-2 "0.0001101" is too big (1/16 + 1/32 + 1/128); base-2 "0.00011001" is too small (1/16 + 1/32 + 1/256); and so on. What we actually need is the infinitely repeating binary number: 0.00011001100110011001100110011... where the 0011s repeat forever. But we cannot do that, since floats only have a fixed number of bits. We have to stop the process somewhere, and get something a tiny bit too small: 0.0001100110011001100110 or a tiny bit too big: 0.0001100110011001100111 depending on exactly how many bits we have available. Is this "inaccurate"? Well, in the sense that it is not the exact true mathematical result, yes it is, but that term can be misleading if you think of it as "a mistake". In another sense, it's not inaccurate, it is as accurate as possible (given the limitation of only having a certain fixed number of bits). -- Steve From alan.gauld at btinternet.com Thu Apr 16 18:12:49 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 16 Apr 2015 17:12:49 +0100 Subject: [Tutor] making a list in Tkinter with clickable items (Python 2.x) In-Reply-To: References: Message-ID: On 16/04/15 11:00, Ali Moradi wrote: > Hi, i want to load a bunch of words from my database into the listbox in > Tkinter, make them clickable, and when i clicked on them the specific > meaning of that word apears in a textbox beside the listbox. > > i have a code but it's not complete. i'm a beginner in Python :( > Focus on getting your UI working first. There are lots of problems below. Sort those then you can focus on the sing;e problem of managing the data, followed by the next single problem of clicking on an item to do something. For now get your foundation working. > code: > #!/bin/python > from tkinter import * > from tkinter import ttk If its Python v2 then you spell it Tkinter (capital T). And ttk lives at the top level in Python 2 not under Tkinter. > def z(): > global entry > if(lb.get(lb.curselection())): > txt.insert(END, lb.get(lb.curselection())) Please use descriptive names for functions, it makes reading the code much easier. Why use global entry when you don't use entry in your function? Also its better practice to use a variable to store the current selection rather than ask for it twice: def transferCurrentSelection(): sel = lb.curselection() content = lb.get(sel) if content: txt.insert(END, content) Its a lot easier to debug if things go wrong. And you can more easily tweak it to become a reusable function too... > root = Tk() > > entry = ttk.Entry(root);entry.grid(row = 0, column = 0) Don't use semi-colons like that, it confuses the code and is very hard to see and differentiate from a period. Nobody will shout at you for using two lines. > lb = Listbox(root) > > a=lb.insert(1, "crime") > b=lb.insert(2, "murder") > lb.insert(3, "get") > lb.insert(4, "take") Why store a and b but not the other two results? In fact insert() returns None anyway so storing it is pointless. > Button(root, text="BUtt", command=z).grid() > > lb.grid(row = 1, column = 0) Its usually better to keep the geometry manager lines beside the widget creation lines. It doesn't hurt if you pack/grid the widget before populating it. > scroll = Scrollbar(root, orient = VERTICAL, command = lb.yview) > scroll.grid(row = 0, column = 1, sticky = 'ns') > lb.config(yscrollcommand = scroll.set) You could have set this when creating the Listbox. Having random lines of code hidden among other widget code makes debugging much harder. > txt = Text(root, width = 60, height = 30,) > txt.grid(row = 1, column = 2) > > root.mainloop() Once you get this working we can revisit the matter of retrieving data from a database, populating the list box and then associating the clicked result with a meaning (from the database presumably?). -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Thu Apr 16 18:47:43 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Thu, 16 Apr 2015 11:47:43 -0500 Subject: [Tutor] How (not!) lengthy should functions be? Message-ID: As I go through my current coding project(s) I find myself breaking functions down into other functions, especially when I see see (unnecessarily) duplicated code fragments. I understand this to be regarded as good practice. However, I am wondering if I am carrying things too far? For instance I have a collection of functions that do simple units conversions such as: def percent2Gy(dose_percent, target_dose_cGy): """ Convert a dose given as a percent of target dose into Gy (Gray). """ dose_Gy = cGy2Gy((dose_percent / 100.0) * target_dose_cGy) return dose_Gy This function calls another units conversion function, cGy2Gy(), in doing its work. Generally speaking, I have units conversions functions for every conversion I currently need to do plus some that I am not using yet because I can easily see the need for them in the future. My current understanding of function length best practice is that: 1) Each function should have preferably ONE clearly defined purpose. 2) I have seen varying recommendations as to number of lines of code per function, but I have seem multiple recommendations that a function generally should fit into one screen on one's monitor. Of course, some people have HUGE monitors! And I assume that any guidance applies equally well to methods. Am I on-track or am I getting carried away? -- boB From dyoo at hashcollision.org Thu Apr 16 19:45:07 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Thu, 16 Apr 2015 10:45:07 -0700 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: > My current understanding of function length best practice is that: 1) > Each function should have preferably ONE clearly defined purpose. Purpose is the biggest factor for me. > 2) I have seen varying recommendations as to number of lines of code per > function, I don't weight this as heavily. I guess I treat physical metrics mostly like guidelines... except for line length, for arbitrary reasons. :P. Anything that goes longer than 80 characters just makes me uncomfortable. I do like short functions, but if some block of code is a few lines longer than average, that's probably ok. What I'd be looking at more closely is the complexity of the statements *in* the function. "Is the function deeply nested?", for example. Just to add: I find that unit testing has an influence on me that encourages writing shorter functions, mostly because the unit testing forces me to make sure the function's easy to test. Kent Beck's "Test Driven Development by Example" talks about this in more depth. From __peter__ at web.de Thu Apr 16 20:43:47 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 16 Apr 2015 20:43:47 +0200 Subject: [Tutor] How (not!) lengthy should functions be? References: Message-ID: boB Stepp wrote: > As I go through my current coding project(s) I find myself breaking > functions down into other functions, especially when I see see > (unnecessarily) duplicated code fragments. I understand this to be > regarded as good practice. However, I am wondering if I am carrying > things too far? For instance I have a collection of functions that do > simple units conversions such as: > > def percent2Gy(dose_percent, target_dose_cGy): > """ > Convert a dose given as a percent of target dose into Gy (Gray). > """ > dose_Gy = cGy2Gy((dose_percent / 100.0) * target_dose_cGy) > return dose_Gy > > This function calls another units conversion function, cGy2Gy(), in > doing its work. Generally speaking, I have units conversions functions > for every conversion I currently need to do plus some that I am not > using yet because I can easily see the need for them in the future. > > My current understanding of function length best practice is that: 1) > Each function should have preferably ONE clearly defined purpose. 2) I > have seen varying recommendations as to number of lines of code per > function, but I have seem multiple recommendations that a function > generally should fit into one screen on one's monitor. Of course, some > people have HUGE monitors! And I assume that any guidance applies > equally well to methods. > > Am I on-track or am I getting carried away? Normally I just stress that functions cannot get too short as both beginners and smart people tend to make them too long. As far as I'm concerned a function with a single line is fine while a function with more than 10 lines needs justification. However, there's more to it. You are working in an environment where people may be harmed if you get your numbers wrong, and nothing hinders you to swap the arguments in your percent2Gy() function or even pass it a length and an amount of dollars. You need measures to make this unlikely. Unambiguous function names and keyword-only parameters (not available in Python 2) and of course tests help, but you might also consider custom types that are restricted to a well-defined set of operations. A sketch: # For illustration purpose only! class Percent: def __init__(self, value): if value < 1 or value > 100: # XXX allow 0%? raise ValueError self.value = value def factor(self): return self.value / 100.0 def __repr__(self): return "{} %".format(self.value) class DoseInGray: def __init__(self, value, **comment): self.value = value self.comment = comment.pop("comment", "") if comment: raise TypeEror def __repr__(self): return "{} Gy # {}".format(self.value, self.comment) def __str__(self): return "{} Gy".format(self.value) class TargetDoseInGray: def __init__(self, value): self.value = value def partial_dose(self, percent): if not isinstance(percent, Percent): raise TypeError return DoseInGray( self.value * percent.factor(), comment="{} of the target dose".format(percent)) def __str__(self): return "{} Gy".format(self.value) if __name__ == "__main__": target_dose = TargetDoseInGray(20) print target_dose partial_dose = target_dose.partial_dose(Percent(10)) print partial_dose print repr(partial_dose) target_dose.partial_dose(0.1) # raises TypeError Output: $ python gray.py 20 Gy 2.0 Gy 2.0 Gy # 10 % of the target dose Traceback (most recent call last): File "gray.py", line 43, in target_dose.partial_dose(0.1) # raises TypeError File "gray.py", line 27, in partial_dose raise TypeError TypeError OK, I got carried away a bit with my example, but you might get an idea where I'm aiming at. The way I wrote it it is pretty clear that Percent(10) denote 10 rather than 1000 %. I can't spare you a last remark: Python may not be the right language to make this bulletproof. From ben+python at benfinney.id.au Thu Apr 16 22:21:14 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Fri, 17 Apr 2015 06:21:14 +1000 Subject: [Tutor] How (not!) lengthy should functions be? References: Message-ID: <85egnju8n9.fsf@benfinney.id.au> boB Stepp writes: > My current understanding of function length best practice is that: 1) > Each function should have preferably ONE clearly defined purpose. Yes, that's a principle to follow firmly, improving the design every time. I know of no exceptions. ?Clearly defined? also entails the function signature (its name, what parameters it accepts, what return value it emits) is narrowly defined. > 2) I have seen varying recommendations as to number of lines of code > per function, but I have seem multiple recommendations that a function > generally should fit into one screen on one's monitor. A function that is clearly-designed, as above, should have no more than a handful of statements. That's intentionally vague, but it's already shorter than ?a screenful?. > Of course, some people have HUGE monitors! And I assume that any > guidance applies equally well to methods. Any function with statements stretching over 20 lines is already too large, IMO. Note that the docstring can be rather lengthy, if there is a lot to say about the function's purpose or strange cases it handles. > Am I on-track or am I getting carried away? You're right to care about precision in your code. Overlong, overbroad, overcomplex, overdetermined functions happen through laziness; it takes diligence to keep the code readable through refactoring while you go. That takes more effort at each edit, but saves a lot of debugging time. Having such a principle in mind, and knowing that it's worth spending effort to uphold, will serve you well. -- \ ?Outside of a dog, a book is man's best friend. Inside of a | `\ dog, it's too dark to read.? ?Groucho Marx | _o__) | Ben Finney From cybervigilante at gmail.com Thu Apr 16 19:24:47 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 16 Apr 2015 10:24:47 -0700 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation Message-ID: > > Is this "inaccurate"? Well, in the sense that it is not the exact true > mathematical result, yes it is, but that term can be misleading if you > think of it as "a mistake". In another sense, it's not inaccurate, it is > as accurate as possible (given the limitation of only having a certain > fixed number of bits). > -- > Steve > --- Understood about the quondam inexactness of floating point bit representation. I was just wondering why the different implementation of representing it when using Fraction(float) as opposed to using Fraction(string(float)). In terms of user presentation, the string usage has smaller numbers for the ratio, so it would be more understandable and should, I assume, be chosen for GUI display. -- Jim The Paleo diet causes Albinism From alan.gauld at btinternet.com Thu Apr 16 23:03:48 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 16 Apr 2015 22:03:48 +0100 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On 16/04/15 17:47, boB Stepp wrote: > things too far? For instance I have a collection of functions that do > simple units conversions such as: > > def percent2Gy(dose_percent, target_dose_cGy): > """ > Convert a dose given as a percent of target dose into Gy (Gray). > """ > dose_Gy = cGy2Gy((dose_percent / 100.0) * target_dose_cGy) > return dose_Gy I tend to draw the line at single liners like the above because by introducing the function you are increasing the complexity of the program. However, very often this kind of thing is justified if: 1) it aids unit testing 2) it makes the code significantly more readable 3) You perform error detection or validation of parameters. Note in this case you could just create an alias percent2GY = cGy2Gy although you then need to do the math when you call it rather than inside the function. > My current understanding of function length best practice is that: 1) > Each function should have preferably ONE clearly defined purpose. By far the most important criteria. It trounces all other arguments. 2) I have seen varying recommendations as to number of lines of code Most of these come from the days when we worked on dumb terminals with 24 line screens. Actual measurements has shown that function length (within reason!) is not a major factor in comprehension or reliability. In COBOL or C it is not unreasonable to have functions over 50 lines long, sometimes over a hundred. But in Python that would be very unusual. So I'd treat the advise to limit length to about 20 lines of executable code to still be valid, if you exceed it treat it as a red flag to check that you really need it to be that long. But splitting a function just to keep the line count down is a terrible idea and more likely to introduce bugs than fix them. The single purpose rule is the guide. > equally well to methods. In practice methods are usually a little bit shorter on average. That's mainly because the data tends to live in object attributes and be pre-formed, whereas a non method often spends significant time reformatting input to the best shape for the function. Also the object attributes were hopefully validated on creation so each method can trust them, again saving lines. > Am I on-track or am I getting carried away? Probably on track. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From wolfgang.maier at biologie.uni-freiburg.de Thu Apr 16 23:04:36 2015 From: wolfgang.maier at biologie.uni-freiburg.de (Wolfgang Maier) Date: Thu, 16 Apr 2015 23:04:36 +0200 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation In-Reply-To: References: Message-ID: On 16.04.2015 19:24, Jim Mooney wrote: > > Understood about the quondam inexactness of floating point bit > representation. I was just wondering why the different implementation of > representing it when using Fraction(float) as opposed to using > Fraction(string(float)). In terms of user presentation, the string usage > has smaller numbers for the ratio, so it would be more understandable and > should, I assume, be chosen for GUI display. > The whole point of the discussion is that this is *not* a presentation issue. Fraction(1.64) and Fraction("1.64") *are* two different numbers because one gets constructed from a value that is not quite 1.64. What sense would it make for Fraction(1.64) to represent itself inexactly ? However, if you really want a shortened, but inexact answer: Fractions have a limit_denominator method that you could use like so: >>> Fraction(1.64).limit_denominator(25) Fraction(41, 25) From danny.yoo at gmail.com Thu Apr 16 23:14:44 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Thu, 16 Apr 2015 14:14:44 -0700 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation In-Reply-To: References: Message-ID: On Apr 16, 2015 1:42 PM, "Jim Mooney" wrote: > Understood about the quondam inexactness of floating point bit > representation. I was just wondering why the different implementation of > representing it when using Fraction(float) as opposed to using > Fraction(string(float)). Ah. Correction. You want to say: .. using Fraction(float) as opposed to using Fraction(**string**). From breamoreboy at yahoo.co.uk Fri Apr 17 00:24:37 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Thu, 16 Apr 2015 23:24:37 +0100 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On 16/04/2015 17:47, boB Stepp wrote: > As I go through my current coding project(s) I find myself breaking > functions down into other functions, especially when I see see > (unnecessarily) duplicated code fragments. I understand this to be > regarded as good practice. However, I am wondering if I am carrying > things too far? For instance I have a collection of functions that do > simple units conversions such as: > > def percent2Gy(dose_percent, target_dose_cGy): > """ > Convert a dose given as a percent of target dose into Gy (Gray). > """ > dose_Gy = cGy2Gy((dose_percent / 100.0) * target_dose_cGy) > return dose_Gy Slight aside, I'd not bother with the dose_Gy, simply:- return cGy2Gy((dose_percent / 100.0) * target_dose_cGy) but see also my comment at the end about aliases. > > This function calls another units conversion function, cGy2Gy(), in > doing its work. Generally speaking, I have units conversions functions > for every conversion I currently need to do plus some that I am not > using yet because I can easily see the need for them in the future. > > My current understanding of function length best practice is that: 1) > Each function should have preferably ONE clearly defined purpose. 2) I > have seen varying recommendations as to number of lines of code per > function, but I have seem multiple recommendations that a function > generally should fit into one screen on one's monitor. Of course, some > people have HUGE monitors! And I assume that any guidance applies > equally well to methods. > > Am I on-track or am I getting carried away? > I'd say pretty much spot on, especially if you take Alan's advice and use aliases instead of the one line functions. I can only assume that you've seen this quote "Always code as if the person who ends up maintaining your code is a violent psychopath who knows where you live." -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From davea at davea.name Fri Apr 17 00:31:50 2015 From: davea at davea.name (Dave Angel) Date: Thu, 16 Apr 2015 18:31:50 -0400 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation In-Reply-To: References: Message-ID: <55303856.3030105@davea.name> On 04/16/2015 01:24 PM, Jim Mooney wrote: >> >> Is this "inaccurate"? Well, in the sense that it is not the exact true >> mathematical result, yes it is, but that term can be misleading if you >> think of it as "a mistake". In another sense, it's not inaccurate, it is >> as accurate as possible (given the limitation of only having a certain >> fixed number of bits). >> -- >> Steve >> > > --- > Understood about the quondam inexactness of floating point bit > representation. I was just wondering why the different implementation of > representing it when using Fraction(float) as opposed to using > Fraction(string(float)). You didn't use str(float), you used a simple str. So there was no quantization error since it was never converted to binary floating point. If you have a number that happens to be an exact decimal number, don't convert it via float(). Either convert it via Decimal() or convert it directly to fraction. In terms of user presentation, the string usage > has smaller numbers for the ratio, so it would be more understandable and > should, I assume, be chosen for GUI display. > Presumably you didn't read my message. When you use a literal 1.64 in your code, you're telling the compiler to call the float() function on the token. You've already forced the quantization error. Nothing to do with the fraction class. -- DaveA From cybervigilante at gmail.com Fri Apr 17 00:11:59 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 16 Apr 2015 15:11:59 -0700 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation In-Reply-To: References: Message-ID: The whole point of the discussion is that this is *not* a presentation issue. Fraction(1.64) and Fraction("1.64") *are* two different numbers because one gets constructed from a value that is not quite 1.64. Wolfgang Maier -- So the longer numerator and denominator would, indeed, be more accurate if used in certain calculations rather than being normalized to a float - such as in a Fortran subroutine or perhaps if exported to a machine with a longer bit-length? That's mainly what I was interested in - if there is any usable difference between the two results. Jim The Paleo diet causes Albinism From alan.gauld at btinternet.com Fri Apr 17 00:40:09 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 16 Apr 2015 23:40:09 +0100 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On 16/04/15 22:03, Alan Gauld wrote: >> def percent2Gy(dose_percent, target_dose_cGy): >> """ >> Convert a dose given as a percent of target dose into Gy (Gray). >> """ >> dose_Gy = cGy2Gy((dose_percent / 100.0) * target_dose_cGy) >> return dose_Gy > > Note in this case you could just create an alias > > percent2GY = cGy2Gy Except that the name would then be misleading - my bad! The value that your function adds is the percentage calculation. But if it is a straight renaming exercise then an alias would be more appropriate than defining a new wrapper function. Sorry, for the bad example. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From breamoreboy at yahoo.co.uk Fri Apr 17 01:04:45 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Fri, 17 Apr 2015 00:04:45 +0100 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On 16/04/2015 23:40, Alan Gauld wrote: > On 16/04/15 22:03, Alan Gauld wrote: > >>> def percent2Gy(dose_percent, target_dose_cGy): >>> """ >>> Convert a dose given as a percent of target dose into Gy (Gray). >>> """ >>> dose_Gy = cGy2Gy((dose_percent / 100.0) * target_dose_cGy) >>> return dose_Gy >> > >> Note in this case you could just create an alias >> >> percent2GY = cGy2Gy > > Except that the name would then be misleading - my bad! > The value that your function adds is the percentage calculation. > > But if it is a straight renaming exercise then an alias would > be more appropriate than defining a new wrapper function. > > Sorry, for the bad example. > Bah, that'll teach me to read more closely in the future :( -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From steve at pearwood.info Fri Apr 17 04:29:10 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 17 Apr 2015 12:29:10 +1000 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation In-Reply-To: References: Message-ID: <20150417022910.GS5663@ando.pearwood.info> On Thu, Apr 16, 2015 at 03:11:59PM -0700, Jim Mooney wrote: > So the longer numerator and denominator would, indeed, be more accurate if > used in certain calculations rather than being normalized to a float - such > as in a Fortran subroutine or perhaps if exported to a machine with a > longer bit-length? That's mainly what I was interested in - if there is any > usable difference between the two results. You're asking simple questions that have complicated answers which probably won't be what you are looking for. But let's try :-) Let's calculate a number. The details don't matter: x = some_calculation(a, b) print(x) which prints 1.64. Great, we have a number that is the closest possible base 2 float to the decimal 164/100. If we convert that float to a fraction *exactly*, we get: py> Fraction(1.64) Fraction(7385903388887613, 4503599627370496) So the binary float which displays as 1.64 is *actually* equal to 7385903388887613/4503599627370496, which is just a tiny bit less than the decimal 1.64: py> Fraction(1.64) - Fraction("1.64") Fraction(-11, 112589990684262400) That's pretty close. The decimal value that normally displays as 1.64 is perhaps more accurately displayed as: py> "%.23f" % 1.64 '1.63999999999999990230037' but even that is not exact. So which is the "right" answer? That depends. (1) It could be that our initial calculation some_calculation(a, b) actually was 164/100, say, in which case the *correct* result should be decimal 1.64 = Fraction("1.64") and the 7385blahblahblah/blahblahblah is just an artifact of the fact that floats are binary. (2) Or it could be that the some_calculation(a, b) result actually was 7385903388887613/4503599627370496, say, in which case it is a mere coincidence that this number displays as 1.64 when treated as a binary float. The long 7385blahblahblah numerator and denominator is exactly correct, and decimal 1.64 is a approximation. There is no way of telling in advance which interpretation is correct. You need to think about the calculation you performed and decide what it means, not just look at the final result. Although... 9 times out of 10, if you get something *close* to an exact decimal, a coincidence is not likely. If you get exactly 0.5 out of a calculation, rather than 0.5000000000001, then it probably should be exactly 1/2. *Probably*. The reality is that very often, the difference isn't that important. The difference between 1.64 inches and 1.63999999999999990230037 inches is probably not going to matter, especially if you are cutting the timber with a chainsaw. -- Steve From robertvstepp at gmail.com Fri Apr 17 15:26:38 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 17 Apr 2015 08:26:38 -0500 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? Message-ID: Solaris 10, Python 2.4.4 Thanks to earlier help from this list, I can now print a particular Tkinter-generated window. But this will only print what is currently viewable on the screen. In the case of scrolled information that is currently outside the viewing area, it would be missed by such a print (Using OS import command, as Peter demonstrated.). This type of print functionality appears in everyday software products, but it is not clear to me (Yet!) how to approach this problem. My initial thoughts are along the lines of: 1) Determine how many rows of information appear in the viewing area. 2) Determine how many total rows of information exist to be printed. 3) Figure out how to programmatically do a *manual* scroll to bring up the hidden scrolled information. 4) Repeatedly apply the printing method. While I can probably make this approach work (It *seems* conceptually simple.), I cannot help but feel there is a much better way... I intend to scour my available Tkinter documentation to see if there are root window level and scrolled area commands that might suggest another approach. And what I am doing now, seeking your collective wisdom... Thanks! -- boB From oscar.j.benjamin at gmail.com Fri Apr 17 16:02:41 2015 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Fri, 17 Apr 2015 15:02:41 +0100 Subject: [Tutor] Fraction - differing interpretations for number and string - presentation In-Reply-To: <20150417022910.GS5663@ando.pearwood.info> References: <20150417022910.GS5663@ando.pearwood.info> Message-ID: On 17 April 2015 at 03:29, Steven D'Aprano wrote: > On Thu, Apr 16, 2015 at 03:11:59PM -0700, Jim Mooney wrote: > >> So the longer numerator and denominator would, indeed, be more accurate if >> used in certain calculations rather than being normalized to a float - such >> as in a Fortran subroutine or perhaps if exported to a machine with a >> longer bit-length? That's mainly what I was interested in - if there is any >> usable difference between the two results. If it's okay to use float and then go onto machines with higher/lower precision then the extra precision must be unnecessary in which case why bother with the Fraction type? If you really need to transfer your float from one program/machine to another then why not just send the decimal representation. Your 64-bit float should be able to round-trip to decimal text and back for any IEEE-754 compliant systems. Writing it as a fraction doesn't gain any extra accuracy. (BTW Python the language guarantees that float is always an IEEE-754 64-bit float on any machine). When you use floats the idea is that you're using fixed-width floating point as an approximation of real numbers. You're expected to know that there will be some rounding and not consider your computation to be exact. So the difference between 1.64 and the nearest IEEE-754 64-bit binary float should be considered small enough not to worry about. It's possible that in your calculations you will also be using functions from the math module such as sin, cos, etc. and these functions cannot be computed *exactly* for an input such as 1.64. However they can be computed up to any desired finite precision so we can always get the nearest possible float which is what the math module will do. When you use the fractions module and the Fraction type the idea is that floating point inexactness is unacceptable to you. You want to perform *exact* arithmetic and convert from other numeric types or text exactly. You won't be able to use functions like sin and cos but that's no loss since you wouldn't be able to get an exact rational result there anyway. Because the Fractions module is designed for the "I want everything to be exact" use case conversion from float to Fraction is performed exactly. Conversion from string or Decimal to Fraction is also exact. The Fraction will also display its exact value when printed and that's what you're seeing. If you really want higher accuracy than float consider ditching it altogether in favour of Fraction which will compute everything you want exactly. However there's no point in doing this if you're also mixing floats into the calculations. float+Fraction coerces to float discarding accuracy and then calculates with floating point rounding. If that's acceptable then don't bother with Fraction in the first place. If not make sure you stick to only using Fraction. > You're asking simple questions that have complicated answers which > probably won't be what you are looking for. But let's try :-) > > Let's calculate a number. The details don't matter: > > x = some_calculation(a, b) > print(x) > > which prints 1.64. Great, we have a number that is the closest possible > base 2 float to the decimal 164/100. If we convert that float to a > fraction *exactly*, we get: > > py> Fraction(1.64) > Fraction(7385903388887613, 4503599627370496) > > So the binary float which displays as 1.64 is *actually* equal to > 7385903388887613/4503599627370496, which is just a tiny bit less than > the decimal 1.64: > > py> Fraction(1.64) - Fraction("1.64") > Fraction(-11, 112589990684262400) > > That's pretty close. The decimal value that normally displays as 1.64 is > perhaps more accurately displayed as: > > py> "%.23f" % 1.64 > '1.63999999999999990230037' > > but even that is not exact. Just to add to Steven's point. The easiest way to see the exact value of a float in decimal format is: >>> import decimal >>> decimal.Decimal(1.64) Decimal('1.6399999999999999023003738329862244427204132080078125') > The reality is that very often, the difference > isn't that important. The difference between > > 1.64 inches > > and > > 1.63999999999999990230037 inches > > is probably not going to matter, especially if you are cutting the > timber with a chainsaw. I once had a job surveying a building site as an engineer's assistant. I'd be holding a reflector stick while he operated the laser sight machine (EDM) from some distance away and spoke to me over the radio. He'd say "mark it 10mm to the left". The marker spray would make a circle that was about 100mm in diameter. Then I would get 4 unevenly shaped stones (that happened to be lying around) and drop them on the ground to mark out the corners of a 1500mm rectangle by eye. Afterwards the excavator would dig a hole there using a bucket that was about 1000mm wide. While digging the stones would get moved around and the operator would end up just vaguely guessing where the original marks had been. The engineer was absolutely insistent that it had to be 10mm to the left though. I think that just naturally happens when you're equipment is more accurate than it needs to be for the task in hand. Oscar From robertvstepp at gmail.com Fri Apr 17 17:05:10 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 17 Apr 2015 10:05:10 -0500 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: <201504171429.t3HETlaG010853@fido.openend.se> References: <201504171429.t3HETlaG010853@fido.openend.se> Message-ID: On Fri, Apr 17, 2015 at 9:29 AM, Laura Creighton wrote: >>While I can probably make this >>approach work (It *seems* conceptually simple.), I cannot help but >>feel there is a much better way... > > Tkinter is very old software. This sort of scrolling you want was > in no way common when Tkinter was new. For things like this, I > just use kivy, which has the advantage that is runs under IOS and > Android out of the box. > > The whole point of kivy is to create better, new paradigm user interfaces, > where scrolling surfaces are built-in. > > It may be faster for you to reimplement what you have in kivy than to > try to get Tkinter to do what you want. Alas! I am not allowed to install any new software on these systems (Which use Python 2.4.4 or 2.6.4.). So I am stuck with whatever tools are installed by default, and that does not include your suggestion. However, I will look into kivy for my at-home studies/projects! -- boB From lac at openend.se Fri Apr 17 16:29:47 2015 From: lac at openend.se (Laura Creighton) Date: Fri, 17 Apr 2015 16:29:47 +0200 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: Message from boB Stepp of "Fri, 17 Apr 2015 08:26:38 -0500." References: Message-ID: <201504171429.t3HETlaG010853@fido.openend.se> >While I can probably make this >approach work (It *seems* conceptually simple.), I cannot help but >feel there is a much better way... Tkinter is very old software. This sort of scrolling you want was in no way common when Tkinter was new. For things like this, I just use kivy, which has the advantage that is runs under IOS and Android out of the box. The whole point of kivy is to create better, new paradigm user interfaces, where scrolling surfaces are built-in. It may be faster for you to reimplement what you have in kivy than to try to get Tkinter to do what you want. Laura From niyanaxx95 at gmail.com Fri Apr 17 20:11:00 2015 From: niyanaxx95 at gmail.com (niyanaxx95 at gmail.com) Date: Fri, 17 Apr 2015 18:11:00 +0000 Subject: [Tutor] =?utf-8?q?=3DLinked_List_Using_Map?= In-Reply-To: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> References: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> Message-ID: <55314cc2.9512370a.1868.ffffd2c5@mx.google.com> Sent from Windows Mail From: Ni'Yana Morgan Sent: ?Friday?, ?April? ?17?, ?2015 ?2?:?06? ?PM To: tutors at python.org Hello I need guidance trying to solve my assignment. I am completely lost when using maps with linked lists. I understand linked lists though. May someone work with me? implement the Map ADT using a singly linked list: ? Map(): Creates a new empty map. ? length(): Returns the number of key/value pairs in the map. ? contains(key): Returns a Boolean indicating if the given key is in the map. ? setitem(key, value): Adds a new key/value pair to the map if the key is not in the map. If the key is in the map, the new value replaces the original value associated with the key. ? getitem(key): Returns the value associated with the given key, which must exist. ? clear(): Clears or empties the map by removing all key/value pairs. ? keys(): Returns a list containing the keys stored in the map. ? values(): Returns a list containing the values stored in the map. ? toString(): Returns a string representation of the map in the following format: {k1:v1, k2:v2, ..., kN:vN} ? min(): Returns the minimum key in the map. The map can not be empty. ? max(): Returns the maximum key in the map. The map can not be empty. ? copy(): Creates and returns a new map that is a duplicate copy of this map. My Code (so far): class Node: def __init__( self, item, next = None ) : self.item = item self.next = next def getItem( self ) : return self.item def getNext( self ) : return self.next def setItem( self, item ) : self.item = item def setNext( self, next ) : self.next = next class Map: def __init__( self, contents = []) : self.first = LinkedList.Node(None, None) self.last = self.first self.numItems = 0 for e in contents: self.append(e) def __len__( self ) : count = 0 while self != None: count +=1 self = self.next return count def contains() : pass def __setitem__( self, index, value ) : if index >= 0 and index < self.numItems: cursor = self.first.getNext() for i in range( index ): cursor = cursor.getNext() return cursor.getItem() def __getitem__( self, index, value ) : if index >= 0 and index < self.numItems: cursor = self.first.getNext() for i in range( index ): cursor = cursor.getNext() cursor.setItem( value ) return From samuel.viscapi at univ-montp2.fr Fri Apr 17 10:39:01 2015 From: samuel.viscapi at univ-montp2.fr (Samuel VISCAPI) Date: Fri, 17 Apr 2015 10:39:01 +0200 Subject: [Tutor] Unicode encoding and raw_input() in Python 2.7 ? Message-ID: <5530C6A5.7010808@univ-montp2.fr> -----BEGIN PGP SIGNED MESSAGE----- Hash: SHA256 Hi, This is my first post to that mailing list if I remember correctly, so hello everyone ! I've been stuck on a simple problem for the past few hours. I'd just like raw_input to work with accentuated characters. For example: firstname = str.capitalize(raw_input('First name: ')) where firstname could be "Val?rie", "Gis?le", "Honor?", etc... I tried -*- coding: utf-8 -*-, u'', unicode(), but to no avail... I'm using str.capitalize and str.lower throughout my code, so I guess some encoding / decoding will also be necessary at some point. Thanks a lot for your help ! Cheers, Samuel -----BEGIN PGP SIGNATURE----- Version: GnuPG v2.0.17 (GNU/Linux) iF4EAREIAAYFAlUwxqUACgkQqjnQbvs+kDn4AAD/YHz55tvBixTgdp16L45tc8Dr /0jyPNg9aMndpwoDlLkA/2SnSWLkeSwI4xM9xKbucx+28I50NcEG/8wx8c31GWll =KI8s -----END PGP SIGNATURE----- From alan.gauld at btinternet.com Fri Apr 17 21:28:21 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 17 Apr 2015 20:28:21 +0100 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: References: Message-ID: On 17/04/15 14:26, boB Stepp wrote: > Solaris 10, Python 2.4.4 > > Thanks to earlier help from this list, I can now print a particular > Tkinter-generated window. But this will only print what is currently > viewable on the screen. Because it is effectively taking a screen shot. > In the case of scrolled information that is > currently outside the viewing area, it would be missed by such a print That's why GUI printing generally uses an entirely different technique to print things (see my earlier email). In essence this requires you to separate the data content and format from the GUI presentation. The printed presentation must be prepared by you the programmer and output to the new display context(a printer). This means you need to decide how to handle page breaks, page width and orientation etc etc. Its a whole different ballgame and much more complex than simply issuing a print command. Hard copy output from a GUI is one of the hardest things to do in almost any GUI, especially if you want it truly WYSIWYG. My personal favourite approach is to abandon WYSIWYG and go for WYSRWYG - What you see resembles what you'll get... And then I reformat the data using HTML, send it to a file and print that file using whatever HTML rendering engine I can find. wxPython makes printing easier but even there its a whole chapter(ch17) of the book and its at the end so assumes you already know all the background around sizers, device context and the like.... The example program - for printing a formatted text document - runs to 2.5 pages of code. And that's the easiest printing framework I've seen. > are along the lines of: 1) Determine how many rows of information > appear in the viewing area. 2) Determine how many total rows of > information exist to be printed. 3) Figure out how to programmatically > do a *manual* scroll to bring up the hidden scrolled information. 4) > Repeatedly apply the printing method. While I can probably make this > approach work (It *seems* conceptually simple.), I cannot help but > feel there is a much better way... Its never going to be pretty but multiple screen captures can work. Its certainly easy enough to reposition a scroll bar programmatically from within a while loop. Figuring out how many lines will depend on all sorts of things like the size of fonts being used, how widgets are laid out. That's what gets tricky, especially if users don't have standardised screen sizes etc. > I intend to scour my available Tkinter documentation to see if there > are root window level and scrolled area commands that might suggest > another approach. Not really. Tkinter (and Tk) basically sidesteps printing to hard copy. There simply is no built in support. You have to format it yourself. Check out IDLE - even it doesn't have any built in formatted print. It only has 'Print Window', which is just plain text. Although even looking at how they did that might help too. Remember you have the code to IDLE and its built using Tkinter... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Fri Apr 17 21:45:38 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 17 Apr 2015 20:45:38 +0100 Subject: [Tutor] =Linked List Using Map In-Reply-To: <55314cc2.9512370a.1868.ffffd2c5@mx.google.com> References: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> <55314cc2.9512370a.1868.ffffd2c5@mx.google.com> Message-ID: On 17/04/15 19:11, niyanaxx95 at gmail.com wrote: > Hello I need guidance trying to solve my assignment. > I am completely lost when using maps with linked lists. > I understand linked lists though. Unfortunately we do not. Linked lists aren't really a native Python type and maps are a native type - the dictionary. So implementing the equivalent of a native type using a non-native type is kind of a bizarre situation. Without knowing how your linked list is built we can't tell you anything about how to build a map(dictionary) from it. > implement the Map ADT using a singly linked list: > ? Map(): Creates a new empty map. > ? length(): Returns the number of key/value pairs in the map. > ? contains(key): Returns a Boolean indicating if the given key is in the map. > ? setitem(key, value): Adds a new key/value pair to the map if the key is not in the map. If the key is in the map, the new value replaces the original value associated with the key. > ? getitem(key): Returns the value associated with the given key, which must exist. > ? clear(): Clears or empties the map by removing all key/value pairs. > ? keys(): Returns a list containing the keys stored in the map. > ? values(): Returns a list containing the values stored in the map. > ? toString(): Returns a string representation of the map in the following format: {k1:v1, k2:v2, ..., kN:vN} > ? min(): Returns the minimum key in the map. The map can not be empty. > ? max(): Returns the maximum key in the map. The map can not be empty. > ? copy(): Creates and returns a new map that is a duplicate copy of this map. That's a pretty hefty API for an assignment of this type! > My Code (so far): I assume that your Node is in a separate file called LinkedList.py? > class Node: > def __init__( self, item, next = None ) : > self.item = item > self.next = next > > def getItem( self ) : > return self.item > > def getNext( self ) : > return self.next > > def setItem( self, item ) : > self.item = item > > def setNext( self, next ) : > self.next = next That all seems fairly normal. > class Map: > > def __init__( self, contents = []) : > self.first = LinkedList.Node(None, None) > self.last = self.first > self.numItems = 0 > > for e in contents: > self.append(e) Where does append() come from? Its not a method of Map. > def __len__( self ) : > count = 0 > while self != None: > count +=1 > self = self.next > return count Notice you were asked to provide a length() method so presumably your __len__() operator should just call self.length(). And if you update self.numItems correctly isn't length() just returning self.numItems? > def contains() : > pass > > def __setitem__( self, index, value ) : > if index >= 0 and index < self.numItems: > cursor = self.first.getNext() > for i in range( index ): > cursor = cursor.getNext() > return cursor.getItem() you seem to have the setItem and getItem actions reversed? > > def __getitem__( self, index, value ) : > if index >= 0 and index < self.numItems: > cursor = self.first.getNext() > for i in range( index ): > cursor = cursor.getNext() > cursor.setItem( value ) > return I suggest you go and have a think about how you will store the key/value pairs needed for a map in your list. Then think about how you find a node by key. Then think about how to get the value or set a new value on that node. I hate when teachers ask students to do stupid stuff like this. It encourages so many bad practices it's positively dangerous! If they must have them reinvent the wheel at least let them use the native Python list to do it! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Fri Apr 17 21:58:10 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 17 Apr 2015 20:58:10 +0100 Subject: [Tutor] Unicode encoding and raw_input() in Python 2.7 ? In-Reply-To: <5530C6A5.7010808@univ-montp2.fr> References: <5530C6A5.7010808@univ-montp2.fr> Message-ID: On 17/04/15 09:39, Samuel VISCAPI wrote: > hello everyone ! Hello, and welcome. > I've been stuck on a simple problem for the past few hours. I'd just > like raw_input to work with accentuated characters. > > For example: > > firstname = str.capitalize(raw_input('First name: ')) > > where firstname could be "Val?rie", "Gis?le", "Honor?", etc... > > I tried -*- coding: utf-8 -*-, u'', unicode(), but to no avail... You know what you tried. We don't so please post again showing us some actual code that you tried and didn't work. Tell us (or show us cut n pasted output) what you got and what you expected. Otherwise we are just guessing. > I'm using str.capitalize and str.lower throughout my code, so I guess > some encoding / decoding will also be necessary at some point. capitalize/lower etc don't really care about encodings. They just work with the string they are given. I'm not sure what extra you think you will need to do. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Fri Apr 17 22:06:35 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 17 Apr 2015 21:06:35 +0100 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: <201504171429.t3HETlaG010853@fido.openend.se> References: <201504171429.t3HETlaG010853@fido.openend.se> Message-ID: On 17/04/15 15:29, Laura Creighton wrote: > just use kivy, which has the advantage that is runs under IOS and > Android out of the box. But does Kivy support hard copy printing? That's pretty unusual behaviour on tablets/phones. If so can you show us a short example of how it works. (Technically off-topic for the tutor list but I'm curious to see how it compares to say, Tkinter) > The whole point of kivy is to create better, new paradigm user interfaces, > where scrolling surfaces are built-in. That wouldn't be on mobile devices then, where the UIs are universally horrible IMHO! :-) They are the very antithesis of good user interface design. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Sat Apr 18 02:37:10 2015 From: davea at davea.name (Dave Angel) Date: Fri, 17 Apr 2015 20:37:10 -0400 Subject: [Tutor] Unicode encoding and raw_input() in Python 2.7 ? In-Reply-To: <5530C6A5.7010808@univ-montp2.fr> References: <5530C6A5.7010808@univ-montp2.fr> Message-ID: <5531A736.9010204@davea.name> On 04/17/2015 04:39 AM, Samuel VISCAPI wrote: > -----BEGIN PGP SIGNED MESSAGE----- > Hash: SHA256 > > Hi, > > This is my first post to that mailing list if I remember correctly, so > hello everyone ! > Welcome to the list. > I've been stuck on a simple problem for the past few hours. I'd just > like raw_input to work with accentuated characters. That should mean you want to use unicode. If you're using raw_input, then you must be using Python 2.x. Easiest first step to doing things right in Unicode would be to switch to version 3.x But I'll assume that you cannot do this, for the duration of this message. > > For example: > > firstname = str.capitalize(raw_input('First name: ')) If you're serious about Unicode, you're getting an encoded string with raw_input, so you'll need to decode it, using whatever encoding your console device is using. If you don't know, you're in big trouble. But if you're in Linux, chances are good that it's utf-8. > > where firstname could be "Val?rie", "Gis?le", "Honor?", etc... > > I tried -*- coding: utf-8 -*-, u'', unicode(), but to no avail... > As Alan says, you're not tellins us anything useful. "No avail" is too imprecise to be useful. I'll comment on them anyway. The coding statement applies only to literals you use in your source code. It has nothing at all to do with the value returned by raw_input. u'' likewise is used in your source code. It has nothing to do with what the user may type into your program. unicode() is a "function" that may decode a string received from raw_input, providing you know what the coding was. You can also accomplish it by using the method str.decode(). > I'm using str.capitalize and str.lower throughout my code, so I guess > some encoding / decoding will also be necessary at some point. Those apply to strings. But if you're doing it right, you should have unicode objects long before you apply such methods. So you'd want the unicode methods unicode.upper and unicode.lower -- DaveA From wallenpb at gmail.com Sat Apr 18 05:16:27 2015 From: wallenpb at gmail.com (Bill Allen) Date: Fri, 17 Apr 2015 22:16:27 -0500 Subject: [Tutor] lists, name semantics Message-ID: If I have a list defined as my_list = ['a','b','c'], what is the is differnce between refering to it as my_list or my_list[:]? These seem equivalent to me. Is that the case? Is there any nuance I am missing here? Situations where one form should be used as opposed to the other? Thanks, Bill Allen From ben+python at benfinney.id.au Sat Apr 18 05:27:55 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Sat, 18 Apr 2015 13:27:55 +1000 Subject: [Tutor] lists, name semantics References: Message-ID: <85pp72qfno.fsf@benfinney.id.au> Bill Allen writes: > If I have a list defined as my_list = ['a','b','c'], what is the is > differnce between refering to it as my_list or my_list[:]? ?my_list? is a reference to the object you've already described (the existing object ?['a', 'b', 'c']?). ?my_list[:]? is an operation that takes the original object and creates a new one by slicing. In this case, the new object happens to be equal to (but probably not identical to) the original, because of the slice you specified. > Is there any nuance I am missing here? Situations where one form > should be used as opposed to the other? You need to understand, when writing code, whether you are intending to refer to the original object, or to create a new one. Neither is better, they are both common but different operations. -- \ ?Our products just aren't engineered for security.? ?Brian | `\ Valentine, senior vice-president of Microsoft Windows | _o__) development, 2002 | Ben Finney From martin at linux-ip.net Sat Apr 18 05:42:11 2015 From: martin at linux-ip.net (Martin A. Brown) Date: Fri, 17 Apr 2015 20:42:11 -0700 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: Good evening Bill, > If I have a list defined as my_list = ['a','b','c'], what is the > is differnce between refering to it as my_list or my_list[:]? > These seem equivalent to me. Is that the case? Is there any > nuance I am missing here? Situations where one form should be > used as opposed to the other? Yes, there is a difference. It can (conceivably) by subtle, but it is simple. Let's start with the following. I will call the list by the variable name l. So, Python ('the computer') has stored the list in memory. After executing this command, if I want to retrieve that data, I can call it by the variable named 'l': l = ['a', 'b', 'c'] Now consider the following two statements. case A: k = l case B: m = l[:] These perform two different operations. The first simply says "Hey, when I refer to variable k, I want it to behave exactly like I had used the variable named l." The second says "Please give me a COPY of everything contained in the variable named l and let me refer to that as the variable named m." What is the nuance of difference? Where are the data stored in memory? Let's take case A: >>> l = ['a', 'b', 'c'] >>> k = l >>> k == l True >>> k is l True So, you see, not only are k and l refer to the same list contents, but they point to the same place in computer memory where the list is stored. The variables named l and k are just different names for the same thing (data). Now, let's see what happens when we use case B, copying the list (strictly speaking you are slicing the entire list, see Python documentation). >>> m = l[:] >>> m == l True >>> m is l False What's different here? Well, the variables m and l have the same contents, and are therefore equal (this will compare all elements of the list for equality). But, m and l are not the same thing (data)! Though they contain the same data, the list contents are stored in different places in computer memory. This subtlety means that you probably do not want to say my_list[:] unless you really want to use up all the memory to store the same data twice. You may wish to do that, but given your question about nuance, I would point out that this is no nuance but a significant feature which can surprise you later if you do not understand what is happening with the slicing notation. Best of luck and enjoy a fried slice of Python! -Martin [0] https://docs.python.org/3/library/stdtypes.html#sequence-types-list-tuple-range -- Martin A. Brown http://linux-ip.net/ From ben+python at benfinney.id.au Sat Apr 18 05:51:05 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Sat, 18 Apr 2015 13:51:05 +1000 Subject: [Tutor] lists, name semantics References: <85pp72qfno.fsf@benfinney.id.au> Message-ID: <85iocuqel2.fsf@benfinney.id.au> Ben Finney writes: > Bill Allen writes: > > > If I have a list defined as my_list = ['a','b','c'], what is the is > > differnce between refering to it as my_list or my_list[:]? > > ?my_list? is a reference to the object you've already described (the > existing object ?['a', 'b', 'c']?). > > ?my_list[:]? is an operation that takes the original object and > creates a new one by slicing. In this case, the new object happens to > be equal to (but probably not identical to) the original, because of > the slice you specified. To demonstrate how identity differs from equality, use the appropriate comparison operators:: $ python3 >>> foo = ['a', 'b', 'c'] >>> bar = foo # Bind the name ?bar? to the same object. >>> bar # Show me the object referred to by ?bar?. ['a', 'b', 'c'] >>> bar == foo # Is the object ?bar? equal to the object ?foo?? True >>> bar is foo # Is ?bar? referring to the same object as ?foo?? True >>> baz = foo[:] # Slice ?foo?, creating a new list; bind ?baz? to that. >>> baz # Show me the object referred to by ?baz?. ['a', 'b', 'c'] >>> baz == foo # Is the object ?baz? equal to the object ?foo?? True >>> baz is foo # Is ?baz? referring to the same object as ?foo?? False References which compare identical *are the same* object, guaranteed. Object identity almost always implies equality. (?almost always? because some object types have unusual behaviour like ?the object is not equal to itself?. Don't fret about that though, these exceptions are clearly defined when you find them.) References which compare equal *may under some conditions* be identical. This is *not* ever a promise, though, and you should never rely on it, not even in the same session of a program. Some of Python's internal optimisations depend on the fact that object equality *does not* imply object identity. If you happen to notice some operations producing the same object at one point in time, but the documentation doesn't promise it, then treat that as an unpredictable implementation detail and don't rely on it in your code. -- \ ?The best in us does not require the worst in us: Our love of | `\ other human beings does not need to be nurtured by delusion.? | _o__) ?Sam Harris, at _Beyond Belief 2006_ | Ben Finney From davea at davea.name Sat Apr 18 07:03:34 2015 From: davea at davea.name (Dave Angel) Date: Sat, 18 Apr 2015 01:03:34 -0400 Subject: [Tutor] lists, name semantics In-Reply-To: <85iocuqel2.fsf@benfinney.id.au> References: <85pp72qfno.fsf@benfinney.id.au> <85iocuqel2.fsf@benfinney.id.au> Message-ID: <5531E5A6.1000601@davea.name> On 04/17/2015 11:51 PM, Ben Finney wrote: > Ben Finney writes: > >> Bill Allen writes: >> >>> If I have a list defined as my_list = ['a','b','c'], what is the is >>> differnce between refering to it as my_list or my_list[:]? >> >> ?my_list? is a reference to the object you've already described (the >> existing object ?['a', 'b', 'c']?). >> >> ?my_list[:]? is an operation that takes the original object and >> creates a new one by slicing. In this case, the new object happens to >> be equal to (but probably not identical to) the original, because of >> the slice you specified. > > To demonstrate how identity differs from equality, use the appropriate > comparison operators:: > > $ python3 > > >>> foo = ['a', 'b', 'c'] > > >>> bar = foo # Bind the name ?bar? to the same object. > >>> bar # Show me the object referred to by ?bar?. > ['a', 'b', 'c'] > >>> bar == foo # Is the object ?bar? equal to the object ?foo?? > True > >>> bar is foo # Is ?bar? referring to the same object as ?foo?? > True > > >>> baz = foo[:] # Slice ?foo?, creating a new list; bind ?baz? to that. > >>> baz # Show me the object referred to by ?baz?. > ['a', 'b', 'c'] > >>> baz == foo # Is the object ?baz? equal to the object ?foo?? > True > >>> baz is foo # Is ?baz? referring to the same object as ?foo?? > False > > References which compare identical *are the same* object, guaranteed. > Object identity almost always implies equality. > > (?almost always? because some object types have unusual behaviour like > ?the object is not equal to itself?. Don't fret about that though, these > exceptions are clearly defined when you find them.) > > > References which compare equal *may under some conditions* be identical. > This is *not* ever a promise, though, and you should never rely on it, > not even in the same session of a program. > > Some of Python's internal optimisations depend on the fact that object > equality *does not* imply object identity. If you happen to notice some > operations producing the same object at one point in time, but the > documentation doesn't promise it, then treat that as an unpredictable > implementation detail and don't rely on it in your code. > Great description, if the OP really wants that level of detail. But I think what he needs to know first is: If you change foo, like (untested) foo[1] = "new" then you'll see that bar also changes (since it's just another name for the exact same object). >>> bar ['a', 'new', 'c'] But baz does not, since it's bound to a copy of the object. >>> baz ['a', 'b', 'c'\ -- DaveA From alan.gauld at btinternet.com Sat Apr 18 08:43:03 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 18 Apr 2015 07:43:03 +0100 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: On 18/04/15 04:16, Bill Allen wrote: > If I have a list defined as my_list = ['a','b','c'], what is the is > differnce between refering to it as my_list or my_list[:]? These seem > equivalent to me. Is that the case? Is there any nuance I am missing > here? Situations where one form should be used as opposed to the other? Others have already given some good explanations. I'll add a slightly different take. Your confusion starts with your first statement: > I have a list defined as my_list = ['a','b','c'] What you should be saying is I have a list defined as ['a', 'b', 'c'] Thats the list object that you are working with. The object is completely separate from the name that you choose to associate with it. You then bound that list to a name: my_list. You could bind it to any number of names but there would still only be one object: foo = my_list bar = foo baz = my_list Now I have 4 names all referring to the same list object. The next source of confusion comes from another mist-statement: > differnce between refering to it as my_list or my_list[:] The [:] at the end is an operator that returns a copy of the list. So when you use it you are NOT referring to the original list at all. You are creating a new copy. So if we now take one of our previous names, say foo, and do: foo = my_list[:] foo no longer refers to your original list ['a','b','c'] but to a completely new copy of that list. If you modify my_list the changes will show up when you look at bar and baz as well. But foo will be unchanged my_list[0] = 'z' print baz -> prints ['z','b','c'] - the same list as my_list print foo -> prints ['a','b','c'] - a different list object Understanding the separation of names from objects in Python is essential to understanding how it works. It is different to many other languages in this respect. And understanding the difference between identity and value is also important. Two completely different objects can have the same value and so appear the same but they are in fact entirely different. Think about two drivers who both buy the exact same model of car. They may look identical, but they are two separate cars. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From lac at openend.se Sat Apr 18 02:04:11 2015 From: lac at openend.se (Laura Creighton) Date: Sat, 18 Apr 2015 02:04:11 +0200 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: Message from Alan Gauld of "Fri, 17 Apr 2015 21:06:35 +0100." References: <201504171429.t3HETlaG010853@fido.openend.se> Message-ID: <201504180004.t3I04BXk031485@fido.openend.se> In a message of Fri, 17 Apr 2015 21:06:35 +0100, Alan Gauld writes: >On 17/04/15 15:29, Laura Creighton wrote: > >> just use kivy, which has the advantage that is runs under IOS and >> Android out of the box. > >But does Kivy support hard copy printing? >That's pretty unusual behaviour on >tablets/phones. Every kivy app lives in precisely one window. This window has a screenshot method. You can bind it to a button, and you will get a png of exactly what your app looks like. Also, every widget has an export_to_png method which you can use to capture the widget and its children. So inside your program you can say -- start at the top of this widget, display the first page, take screenshot, then scroll it one page, take screenshot, repeat until done. Which is a whole lot easier than fidding with your app and taking screenshots from the outside. Once you have the filename(s) you can print it/them however you normally print files. My printer lives on a wireless conection and my laptop, my desktop and my tablet know how to talk to it. (My phone does not, but it's over 5 years old now, and the android it runs is very old. I'd upgrade it in a second if some manufacturer would go back to making a 3.5 inch screen. A phone that I cannot dial phone numbers on, one handed, is of no use to me. Grumble grumble.) >> The whole point of kivy is to create better, new paradigm user interfaces, >> where scrolling surfaces are built-in. > >That wouldn't be on mobile devices then, >where the UIs are universally horrible IMHO! :-) >They are the very antithesis of good user >interface design. You might enjoy playing with kivy, then, where the philosophy is 'we can do much better than what we have now'. Thinking about touch devices and how to best use them (rather than how to emulate a mouse) is fun. >Alan G >Author of the Learn to Program web site >http://www.alan-g.me.uk/ >http://www.amazon.com/author/alan_gauld Laura Creighton From wallenpb at gmail.com Sat Apr 18 13:55:46 2015 From: wallenpb at gmail.com (Bill Allen) Date: Sat, 18 Apr 2015 06:55:46 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: Everyone that responded, Thanks very much for the excellent explanations! The distinction between a reference to an object and a seperate copy of the object is quite clear now. --Bill On Apr 18, 2015 1:44 AM, "Alan Gauld" wrote: > On 18/04/15 04:16, Bill Allen wrote: > >> If I have a list defined as my_list = ['a','b','c'], what is the is >> differnce between refering to it as my_list or my_list[:]? These seem >> equivalent to me. Is that the case? Is there any nuance I am missing >> here? Situations where one form should be used as opposed to the other? >> > > Others have already given some good explanations. > I'll add a slightly different take. > > Your confusion starts with your first statement: > > > I have a list defined as my_list = ['a','b','c'] > > What you should be saying is > > I have a list defined as ['a', 'b', 'c'] > > Thats the list object that you are working with. The object is completely > separate from the name that you choose to associate > with it. > > You then bound that list to a name: my_list. > You could bind it to any number of names but > there would still only be one object: > > foo = my_list > bar = foo > baz = my_list > > Now I have 4 names all referring to the same list object. > > The next source of confusion comes from another mist-statement: > > > differnce between refering to it as my_list or my_list[:] > > The [:] at the end is an operator that returns a copy of the list. > So when you use it you are NOT referring to the original list > at all. You are creating a new copy. > > So if we now take one of our previous names, say foo, and do: > > foo = my_list[:] > > foo no longer refers to your original list ['a','b','c'] > but to a completely new copy of that list. > > If you modify my_list the changes will show up when you look > at bar and baz as well. But foo will be unchanged > > my_list[0] = 'z' > print baz -> prints ['z','b','c'] - the same list as my_list > print foo -> prints ['a','b','c'] - a different list object > > Understanding the separation of names from objects in Python is essential > to understanding how it works. It is different to many > other languages in this respect. > > And understanding the difference between identity and value is also > important. Two completely different objects can have the same value > and so appear the same but they are in fact entirely different. > Think about two drivers who both buy the exact same model of car. > They may look identical, but they are two separate cars. > > HTH > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From __peter__ at web.de Sat Apr 18 14:49:19 2015 From: __peter__ at web.de (Peter Otten) Date: Sat, 18 Apr 2015 14:49:19 +0200 Subject: [Tutor] lists, name semantics References: Message-ID: Bill Allen wrote: > Everyone that responded, > > Thanks very much for the excellent explanations! The distinction between > a reference to an object and a seperate copy of the object is quite clear > now. You can test your newfound knowledge by predicting the output of the following script: a = [1, ["x", "y"], 3] b = a[:] a[1][1] = "hello!" print(a) # [1, ['x', 'hello!'], 3] print(b) # what will that print? Think twice before you answer. What is copied, what is referenced? From joel.goldstick at gmail.com Sat Apr 18 16:30:38 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Sat, 18 Apr 2015 10:30:38 -0400 Subject: [Tutor] =Linked List Using Map In-Reply-To: References: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> <55314cc2.9512370a.1868.ffffd2c5@mx.google.com> Message-ID: > > > I hate when teachers ask students to do stupid stuff like this. > It encourages so many bad practices it's positively dangerous! > If they must have them reinvent the wheel at least let them > use the native Python list to do it! > > I suspect that the instructor is using Python as a second language, and is picking examples from that language. The use of non-standard names strengthen's my opinion > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From robertvstepp at gmail.com Sat Apr 18 19:03:08 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 12:03:08 -0500 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: <201504180004.t3I04BXk031485@fido.openend.se> References: <201504171429.t3HETlaG010853@fido.openend.se> <201504180004.t3I04BXk031485@fido.openend.se> Message-ID: On Fri, Apr 17, 2015 at 7:04 PM, Laura Creighton wrote: > In a message of Fri, 17 Apr 2015 21:06:35 +0100, Alan Gauld writes: >>On 17/04/15 15:29, Laura Creighton wrote: >> >>> just use kivy, which has the advantage that is runs under IOS and >>> Android out of the box. >> >>But does Kivy support hard copy printing? >>That's pretty unusual behaviour on >>tablets/phones. > > Every kivy app lives in precisely one window. This window has a screenshot > method. You can bind it to a button, and you will get a png of exactly > what your app looks like. > > Also, every widget has an export_to_png method which you can use to > capture the widget and its children. Have these types of methods ever been considered for tkinter? They would go a long way to giving people a way to print, while not getting into a lot of OS hassle. In my particular scenario I would desire the ability to output both postscript and pdf, though if I have the first it is easy to get the latter. boB Stepp From robertvstepp at gmail.com Sat Apr 18 19:15:07 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 12:15:07 -0500 Subject: [Tutor] Star imports, was Re: How to get a Tkinter window to print a color copy of itself as a .pdf file? In-Reply-To: References: Message-ID: On Thu, Apr 16, 2015 at 2:54 AM, Peter Otten <__peter__ at web.de> wrote: > boB Stepp wrote: > >>> import Tkinter as tk >> >> Question: I have been using "from Tkinter import *" as suggested in >> "Programming Python" by Lutz. He remarks that unlike other situations, >> this is generally safe with Tkinter. Is there a benefit to doing the >> import as you have? > > It's a stylistic preference: I like to keep namespaces separate. After reading your full post, you have convinced *me* this is more than stylistic preference. > When I make an exception, typically for generic functionality like > > contextmanager, groupby, namedtuple, defaultdict... > > I import these in a controlled way with > > from collections import defaultdict > from itertools import islice, zip_longest Making it very clear to anyone who comes later. > etc., use them as "pseudo-builtins", and avoid writing functions with the > same name myself. By contrast I have no clear idea of what's in the tkinter > package and might write my own getint() function, say, thus forcing a reader > to scan the complete module to learn which getint() is used. This in particular applies to me at my current stage of learning as I have only scattered knowledge of all that is in the tkinter package. > This is a general problem of star imports; when you overwrite an imported > name you typically don't care or even know about that name in the imported > module. When you read your module later to fix or amend something your > knowledge may have grown, and you expect the imported function where the > custom function is used. This confusion becomes even more likely when a > second developer is involved. You are so persuasive here that forthwith I will change to a substantially explicit format of importing! -- boB From robertvstepp at gmail.com Sat Apr 18 21:01:19 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 14:01:19 -0500 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On Thu, Apr 16, 2015 at 1:43 PM, Peter Otten <__peter__ at web.de> wrote: > However, there's more to it. You are working in an environment where people > may be harmed if you get your numbers wrong, and nothing hinders you to swap > the arguments in your percent2Gy() function or even pass it a length and an > amount of dollars. You need measures to make this unlikely. I am attempting to do this. In a large sense, the whole purpose of my program is to evaluate what the planner has already done. The planner at this point would normally believe he has a deliverable plan that satisfies everything his physician requires. At this point he would normally have the physician review his plan and approve it. The planner has this degree of certainty at this point. The point of this program is to provide additional checking to ensure nothing has been overlooked by the planner before he presents the plan to the physician. The program changes nothing in his plan. It is just a reader of existing plan data and then evaluates it against a variety of criteria. The planner *should* have already done this process himself. The program merely double-checks everything (And adds additional checking that I believe should be done, but not necessarily all of my colleagues agree with me on this.). > Unambiguous function names and keyword-only parameters (not available in > Python 2) and of course tests help, but you might also consider custom types > that are restricted to a well-defined set of operations. A sketch: I do check the numbers and units both for falling within a proper range of allowed values and correct associated units for what is being measured. This happens at several places, but not every place where the information is is used. But data is checked as it enters the workflow and at multiple points during the program's workflow and finally at the end result. Since I am not writing classes yet I am not taking this approach yet. But I see a greater value in doing it this way as the information would be constantly checked for validity. > # For illustration purpose only! > class Percent: > def __init__(self, value): > if value < 1 or value > 100: # XXX allow 0%? > raise ValueError > self.value = value > def factor(self): > return self.value / 100.0 > def __repr__(self): > return "{} %".format(self.value) Something like this would have to be tweaked depending on what structure and what parameter is being evaluated. Actual dose to *something* in the patient can vary between 0% (For something receiving essentially no dose--far from the area of treatment.) to the value of point of maximum dose, which, for an SBRT-type plan, could be as high as 160% of prescription dose. Of course such high doses are only allowed to occur within the confines of the tumor being treated (NEVER outside of it!). [...] > target_dose.partial_dose(0.1) # raises TypeError > > Output: > > $ python gray.py > 20 Gy > 2.0 Gy > 2.0 Gy # 10 % of the target dose > Traceback (most recent call last): > File "gray.py", line 43, in > target_dose.partial_dose(0.1) # raises TypeError > File "gray.py", line 27, in partial_dose > raise TypeError > TypeError I generate an output very similar to this except I must get the error to show up in the planning system software. I rephrase the error message into language that the planner will understand that makes sense in the context of his plan. If it is an issue with his plan, he will know exactly what the issue is and how to address it. For errors that indicate an issue with my coding the planner would receive a message that states where within the program the error occurred, using language that will make sense to the planner, but also pinpoint exactly where the error was generated. And to contact me immediately with the issue. > OK, I got carried away a bit with my example, but you might get an idea > where I'm aiming at. The way I wrote it it is pretty clear that Percent(10) > denote 10 rather than 1000 %. Amen! > I can't spare you a last remark: Python may not be the right language to > make this bulletproof. Would you elaborate on this? I am sure I don't have the experience with programming and programming languages to truly understand your point. As I final note I want to emphasize that I am not writing a program to *create* a treatment plan. Nor am I writing a program that can *alter* an existing treatment plan. It is merely reading output from the treatment plan and evaluating that output against agreed upon best practice numbers. If this program never gets implemented it will change nothing in how plans are created and implemented. If it does get implemented, then the planner will do what he would have done anyway in the absence of the program. However, if the program flags something for his attention, then something will get noticed that might not have. I wish to emphasize that most of these *somethings* would not be actual errors that would cause any harm to a patient; instead, it would suggest ways the planner can make his viable treatment plan even better: Improve target coverage even more; notice that organ x's sparing could be improved without decreasing target coverage; etc. Even though I am attempting to make this program as *bulletproof* as my knowledge and experience allows, it cannot affect anyone's treatment. It is purely a supplemental level of checking, much like the many, ... , many human checks that we already implement. And this feedback, whether human or program-based, is to make a good plan even better, which will result in even better patient outcomes. boB From robertvstepp at gmail.com Sat Apr 18 21:30:12 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 14:30:12 -0500 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On Thu, Apr 16, 2015 at 4:03 PM, Alan Gauld wrote: > On 16/04/15 17:47, boB Stepp wrote: [...] > 2) I have seen varying recommendations as to number of lines of code > > Most of these come from the days when we worked on dumb terminals with 24 > line screens. Actual measurements has shown that function length (within > reason!) is not a major factor in comprehension or reliability. In COBOL or > C it is not unreasonable to have functions over 50 lines long, sometimes > over a hundred. But in Python that would be very unusual. So I'd treat the > advise to limit length to about 20 lines of executable code to still be > valid, if you exceed it treat it as a red flag to check that you really need > it to be that long. Would not your comments above apply to line length as well? If yes, why are we still wedded to a 79-80 character limit to lines when most people's monitors are quite expansive, to put it mildly? boB From alan.gauld at btinternet.com Sat Apr 18 22:05:51 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 18 Apr 2015 21:05:51 +0100 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: On 18/04/15 20:30, boB Stepp wrote: >> line screens. Actual measurements has shown that function length (within >> reason!) is not a major factor in comprehension or reliability. > > Would not your comments above apply to line length as well? Actually no. Research has shown that people's comprehension hits a limit with lines around 12-15 words long. That's about 70 characters. So translating that (text based) metric to code means the 80 character limit is still quite sane. Although I have written code with a limit of 130 chars (on an old VT330 that had a "wide" setting and could print out on a 30inch line printer)... But there is a reason most books are portrait format and use the font sizes they do. (and why newspapers use columns). It's the limits of human comprehensibility. A topic that has been studied in some depth, not just in CompSci but also in graphics design, linguistics and journalism. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Sat Apr 18 22:13:10 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 18 Apr 2015 21:13:10 +0100 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: References: <201504171429.t3HETlaG010853@fido.openend.se> <201504180004.t3I04BXk031485@fido.openend.se> Message-ID: On 18/04/15 18:03, boB Stepp wrote: > Have these types of methods ever been considered for tkinter? I don't follow the TK and Tkinter mailing lists closely. You are probably better asking there. There is a gmane news feed for a Tkinter mailing list as well as an archive gmane.comp.python.tkinter And the general Tk fora at: www.tcl.tk They may even have a solution, in which case let us know. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Sat Apr 18 22:17:42 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 15:17:42 -0500 Subject: [Tutor] How to print ALL contents of a scrolled Tkinter window? In-Reply-To: References: Message-ID: On Fri, Apr 17, 2015 at 2:28 PM, Alan Gauld wrote: > On 17/04/15 14:26, boB Stepp wrote: >> >> Solaris 10, Python 2.4.4 >> [...] > That's why GUI printing generally uses an entirely different > technique to print things (see my earlier email). In essence > this requires you to separate the data content and format > from the GUI presentation. The printed presentation must be > prepared by you the programmer and output to the new display > context(a printer). This means you need to decide how to > handle page breaks, page width and orientation etc etc. I had started thinking along these lines, but realized that I possess a severe lack of knowledge as to the details of the printer does its *magic*. I used to know a bit about how dot-matrix printers (non-color) worked, but that has been a very long time ago... You mentioned groff in the other thread. Is this relatively easy to adapt to its formatting commands? Is it likely to be on my bare-bones Solaris 10 workstation? I will have to check to see what is present Monday. > Its a whole different ballgame and much more complex than > simply issuing a print command. Hard copy output from a > GUI is one of the hardest things to do in almost any GUI, > especially if you want it truly WYSIWYG. I am surprised that Python does not have a standard library module to help with this. I see that there are third-party modules, but that does not help me within my work environment constraints. > My personal favourite approach is to abandon WYSIWYG and > go for WYSRWYG - What you see resembles what you'll get... > And then I reformat the data using HTML, send it to a file > and print that file using whatever HTML rendering engine > I can find. Are there such HTML rendering engines likely to be present in a Solaris 10 environment, which is a rather bare-bones environment? I mean outside of a web browser. I can already use my existing template to auto-generate the appropriate HTML formatting (Once I write the needed functions to do so. But it should logically no different than how I interpret my template to render the Tkinter GUI display.), save that in a file and then? This would be needed to be done programmatically, not manually by the user. The desired end result is a pdf document to be stored electronically for posterity. > wxPython makes printing easier but even there its a > whole chapter(ch17) of the book and its at the end so > assumes you already know all the background around sizers, > device context and the like.... The example program - for > printing a formatted text document - runs to 2.5 pages of > code. And that's the easiest printing framework I've seen. Which book are you referencing here? Would it be "Wxpython in Action"? >> are along the lines of: 1) Determine how many rows of information >> appear in the viewing area. 2) Determine how many total rows of >> information exist to be printed. 3) Figure out how to programmatically >> do a *manual* scroll to bring up the hidden scrolled information. 4) >> Repeatedly apply the printing method. While I can probably make this >> approach work (It *seems* conceptually simple.), I cannot help but >> feel there is a much better way... > > > Its never going to be pretty but multiple screen captures > can work. Its certainly easy enough to reposition a scroll > bar programmatically from within a while loop. Figuring out > how many lines will depend on all sorts of things like > the size of fonts being used, how widgets are laid out. > That's what gets tricky, especially if users don't have > standardised screen sizes etc. I may or may not go this way. I already wrote a set of scripts (in shell and Perl) a few years ago to allow the user to click and drag an area of their screen to capture into a pdf document. It leverages the existing printer configurations and tools in the planning software. When the user is finishing making captures, he clicks the "Print to pdf" button and it converts the captures into a single pdf document, which it then ftps to the desired destination folder on a different portion of our intranet. This would provide a workable solution until I learn more. >> I intend to scour my available Tkinter documentation to see if there >> are root window level and scrolled area commands that might suggest >> another approach. > > > Not really. Tkinter (and Tk) basically sidesteps printing > to hard copy. There simply is no built in support. You have > to format it yourself. I did not find even a hint of anything beyond the already known Canvas widget postscript capability. > Check out IDLE - even it doesn't have any built in > formatted print. It only has 'Print Window', which is > just plain text. > Although even looking at how they did that might > help too. Remember you have the code to IDLE and > its built using Tkinter... I will make time to do this. Hopefully it will provide better modes of thinking on my part! Thanks, Alan! boB From wallenpb at gmail.com Sat Apr 18 22:28:58 2015 From: wallenpb at gmail.com (Bill Allen) Date: Sat, 18 Apr 2015 15:28:58 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: print(b) will print the original copy of a which b now references which is [1, ["x", "y"], 3] On Apr 18, 2015 7:50 AM, "Peter Otten" <__peter__ at web.de> wrote: > Bill Allen wrote: > > > Everyone that responded, > > > > Thanks very much for the excellent explanations! The distinction between > > a reference to an object and a seperate copy of the object is quite clear > > now. > > You can test your newfound knowledge by predicting the output of the > following script: > > > a = [1, ["x", "y"], 3] > b = a[:] > > a[1][1] = "hello!" > > print(a) # [1, ['x', 'hello!'], 3] > print(b) # what will that print? > > Think twice before you answer. What is copied, what is referenced? > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From robertvstepp at gmail.com Sat Apr 18 23:10:32 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 16:10:32 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: On Sat, Apr 18, 2015 at 3:28 PM, Bill Allen wrote: > On Apr 18, 2015 7:50 AM, "Peter Otten" <__peter__ at web.de> wrote: > >> Bill Allen wrote: >> >> > Everyone that responded, >> > >> > Thanks very much for the excellent explanations! The distinction between >> > a reference to an object and a seperate copy of the object is quite clear >> > now. >> >> You can test your newfound knowledge by predicting the output of the >> following script: >> >> >> a = [1, ["x", "y"], 3] >> b = a[:] >> >> a[1][1] = "hello!" >> >> print(a) # [1, ['x', 'hello!'], 3] >> print(b) # what will that print? >> >> Think twice before you answer. What is copied, what is referenced? > print(b) will print the original copy of a which b now references which is > [1, ["x", "y"], 3] Uh, oh! You should have checked your work in the interpreter before replying! Peter is being very tricky!! (At least for me...) Look again at that list inside of a list and... boB P.S.: Watch out for top-posting. That tends to get peopled riled. I moved your response back into the normal flow of the interleaved conversation. From davea at davea.name Sun Apr 19 00:46:37 2015 From: davea at davea.name (Dave Angel) Date: Sat, 18 Apr 2015 18:46:37 -0400 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: References: Message-ID: <5532DECD.3040800@davea.name> On 04/18/2015 03:01 PM, boB Stepp wrote: > > As I final note I want to emphasize that I am not writing a program to > *create* a treatment plan. Nor am I writing a program that can *alter* > an existing treatment plan. It is merely reading output from the > treatment plan and evaluating that output against agreed upon best > practice numbers. If this program never gets implemented it will > change nothing in how plans are created and implemented. If it does I'd still point out that eventually people will presumably get to believing in your program. They'll subconsciously assume that if they mess up, the program will notice, so they don't have to be as careful as they otherwise would. There's nothing you can do about this; it's human nature. So I claim that making sure the advice your program offers has 1) few bugs. And what it has should be crashes, not just getting the wrong result. 2) Careful wording of the messages to indicate the confidence level of the conclusion it's relating. -- DaveA From steve at pearwood.info Sun Apr 19 05:02:33 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 19 Apr 2015 13:02:33 +1000 Subject: [Tutor] =Linked List Using Map In-Reply-To: <55314cc2.9512370a.1868.ffffd2c5@mx.google.com> References: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> <55314cc2.9512370a.1868.ffffd2c5@mx.google.com> Message-ID: <20150419030232.GA5663@ando.pearwood.info> Hello Ni'Yana, and welcome! On Fri, Apr 17, 2015 at 06:11:00PM +0000, niyanaxx95 at gmail.com wrote: > Hello I need guidance trying to solve my assignment. I am completely > lost when using maps with linked lists. I understand linked lists > though. May someone work with me? We will not do your homework, but perhaps we can guide you. Thank you for showing your code. It looks like you have already made a lot of progress. Unfortunately, the one thing you did not tell us is what part of the assignment you are having problems with! It looks like you have done most of the work correctly so far, so what part is giving you trouble? A few comments on your code below: > class Node: > def __init__( self, item, next = None ) : > self.item = item > self.next = next > def getItem( self ) : > return self.item > def getNext( self ) : > return self.next > def setItem( self, item ) : > self.item = item > def setNext( self, next ) : > self.next = next Your Node class looks straightforward, but it doesn't match the requirements. The requirement for the Map is that it must have key:value pairs. But your Node doesn't have two data fields, it only has one! So you cannot give the Node both a key and a value. Your Node class needs to start like this: class Node: def __init__(self, key, value, next=None): self.key = key self.value = value self.next = next That will help get the Map class right. See my comments below. > class Map: > def __init__( self, contents = []) : > self.first = LinkedList.Node(None, None) First problem: you have added code which is not part of the specifications. The assignment says that calling Map() returns a new empty map. It says nothing about Map([1, 2, 3]). Get rid of the "contents" argument, it is not required. Once you get rid of that, the "for e in contents" loop is not required. Get rid of it! Second problem: LinkedList is not defined anywhere. What is it? The easiest way for this to work is to put the None class and the Map class in the same file, and then you can just say: self.first = Node(None, None) without worrying about the name of the file. Java has a rule that each class, no matter how tiny, must go in its own file, but Python does not have such a rule. Related classes may go in the same file. Third problem: your assignment to self.first is wrong! That gives the Map a single item, not zero items! An empty linked list will be represented here by just None alone. self.first = None You then traverse the linked list like this: node = self.first while node is not None: print("key = %s, value = %s" % (node.key, node.value)) node = node.next which will print all the keys and values in the map. To add a new node to the end, you do this: node = self.first # The empty Map case is special. if node is None: self.first = Node("the key", "some value") else: while node.next is not None: node = node.next # Now we are at the end of the linked list. # Add a new node. node.next = Node("the key", "some value") > self.last = self.first > self.numItems = 0 > for e in contents: > self.append(e) > > def __len__( self ) : > count = 0 > while self != None: > count +=1 > self = self.next > return count I don't think that this will do what your assignment asks. The first problem is that your assignment says that your Map must have a method called `length` which returns the number of items. Your Map class has no method called `length`, instead it uses the Python special __len__ method. I think you need to change the name of this __len__ method to length. It is still be buggy (have you tested it?) but at least it will do what the assignment says. Let us think about how to implement this length method. It is actually very easy! Your Map class already has a counter which tell you how many items are in the map, and it is initialised with: self.numItems = 0 so length is easy: def length(self): return self.numItems Now all you need to do is make sure that every time you add a node to the Map, add 1 to numItems, and every time you delete a node, you subtract 1. > def contains() : > pass I assume this is just a stub which is not finished yet. The contains method just needs to walk the linked list and look for the key. I showed you code above that walks the linked list printing keys and values. Instead of printing, you compare the node's key to the key you are looking for, and if they are equal, return True: while node is not None: if node.key == key: return True If you reach the end of the linked list without finding the key, you have to return False. Both your __setitem__ and __getitem__ methods also ignore what the assignment says. The assignment wants methods called `setitem` and `getitem`, not the special Python double-underscore methods. So you need to change their names, then test them. Also, they fail to do what the assignment says. Read the requirements: getitem(key): Returns the value associated with the given key, which must exist. Does your __getitem__ method take a key as argument? No it does not, it takes an index! getitem needs to take a single argument, the key. It then walks the linked list (as I showed you above), comparing the node's key to the wanted key. If they are equal, you then return node.value. If they are not equal, go on to the next node. If you run out of nodes before finding the key, that is an error. setitem needs to take two arguments, a key and a value. You then walk the linked list (again!) and compare the node's key to the wanted key. If they are equal, you set the node's value to the new value: node.value = value and return. If you run out of nodes, you add a new node at the end. Remember what I said about incrementing the counter! By this time, you should see a pattern. Nearly all these methods demonstrate the same sort of procedure: you walk the linked list, looking at each node in turn: node = self.first while node is not None: do_something_with(node) -- Steve From wallenpb at gmail.com Sun Apr 19 05:03:56 2015 From: wallenpb at gmail.com (Bill Allen) Date: Sat, 18 Apr 2015 22:03:56 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: On Apr 18, 2015 4:11 PM, "boB Stepp" wrote: > > On Sat, Apr 18, 2015 at 3:28 PM, Bill Allen wrote: > > On Apr 18, 2015 7:50 AM, "Peter Otten" <__peter__ at web.de> wrote: > > > >> Bill Allen wrote: > >> > >> > Everyone that responded, > >> > > >> > Thanks very much for the excellent explanations! The distinction between > >> > a reference to an object and a seperate copy of the object is quite clear > >> > now. > >> > >> You can test your newfound knowledge by predicting the output of the > >> following script: > >> > >> > >> a = [1, ["x", "y"], 3] > >> b = a[:] > >> > >> a[1][1] = "hello!" > >> > >> print(a) # [1, ['x', 'hello!'], 3] > >> print(b) # what will that print? > >> > >> Think twice before you answer. What is copied, what is referenced? > > > print(b) will print the original copy of a which b now references which is > > [1, ["x", "y"], 3] > > Uh, oh! You should have checked your work in the interpreter before > replying! Peter is being very tricky!! (At least for me...) Look again > at that list inside of a list and... > > boB > > P.S.: Watch out for top-posting. That tends to get peopled riled. I > moved your response back into the normal flow of the interleaved boB, Ok, just tried it out. In this example b=a and b=a[:] seem to yield the same results even after the change to a, which I do not understand. Should not b be a copy of a and not reflect the change? --bill From robertvstepp at gmail.com Sun Apr 19 05:28:39 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 22:28:39 -0500 Subject: [Tutor] How (not!) lengthy should functions be? In-Reply-To: <5532DECD.3040800@davea.name> References: <5532DECD.3040800@davea.name> Message-ID: On Sat, Apr 18, 2015 at 5:46 PM, Dave Angel wrote: > I'd still point out that eventually people will presumably get to believing > in your program. They'll subconsciously assume that if they mess up, the > program will notice, so they don't have to be as careful as they otherwise > would. Well understood! I have observed this in other things I have done that are being used, including the ancestor of this current project. I do not believe I have spoken much of it. It had been in use for approximately one year when I first discovered python and this mailing list. It is similarly a plan evaluation program, except it is used for the evaluation of our SBRT (stereotactic body radiation therapy) plans, whereas this project in development will be used -- at least initially-- to evaluate *normal* treatment plans. I think it has been in continuous use for going on four years now. It has never given an incorrect result. It has never failed its monthly constancy checks. It has rarely had a bug arise. When it has happened, it has been for something a user tried to do that I never imagined happening. But in each such instance (Keep fingers crossed, etc.) it has either crashed or displayed an error message describing the error, stopped program execution, and to contact me. The problem with this program is at the time of creating it, I knew its design was bad, but I did not have any options at the time. I needed the ability to display a graphical display of the plan analysis, but the only option our castrated work stations provided was to use the planning system's ability to create and display GUI elements. All of our workstations had Perl installed, but were missing dependencies (Which I was not allowed to correct.) to allow for GUI generation. I could have investigated the early versions of Java installed, but I wasn't prepared to go that route then. I tentatively looked into C/C++, but initial investigations revealed missing libraries, etc. there as well. So in the end I developed this hybrid of Perl code and planning system scripting language. You would not like the structure of the scripting language! I could go on quite a while, but I'll just mention that ALL variables are essentially both global and persistent. The variables and what they store do not go away until you exit the plan or purposefully destroy them. If I run one script, finish it and run a totally unrelated script it will have access to all variables and their last contents from the previous script unless the programmer explicitly destroyed those variables prior to that script's termination. Talk about potentially clashing namespaces! Because of these and other limitations that I had to work with, I was forced to have some program logic and substantial portions of the constraint data integrated with the GUI generation code. This led to maintenance hell the one time the constraint data had changed almost a couple of years ago. Steven's analogy of hammering nails with a paint brush comes to mind! But I got it to work and to work well. And this is much better than planners repeatedly doing by-hand calculations over and over and ... and over while they are trying to develop a viable plan. Which process is more likely to develop a patient critical error? Especially as the planner becomes fatigued under potentially heavy patient loads, where he must develop plans under time pressures? So I provided a solution that works. The planner uses it as a tool while developing his plans, undoubtedly *not* checking *any* of the calculations he used to do by hand. SUBSTANTIAL amounts of human labor are saved. When the planner feels he has a good plan, THEN he checks all of the program's calculations. If this is satisfactory, then he proceeds to getting the physician, etc. I believe that I come across on this list as much more ignorant and perhaps even much stupider than I actually am. This is because I am the sort of person who is unafraid to ask questions, no matter how trivial or how stupid I might make myself look by doing the asking. I would rather be absolutely certain that I understand what I am trying to do and the implications of what I am trying to do, then not ask due to potential embarrassment. At the very least, I want to identify the boundaries of my ignorance and incompetence. And after further pondering, if I feel I am still missing the boat on something, I'll have a go at asking again until I am satisfied with my comprehension. That is why I am so grateful to have access to your willing help and expertise! Anyway, back to the current project: The moment that they upgraded our systems, so that not only did I have full access to Python, no matter how old, but also that Tkinter was fully installed, was the moment I started designing a complete rewrite of the above-mentioned program. No matter how well working the program currently is, I *must* correct its major design flaws now that I have the tools available to do so. And I much prefer editing data files to editing programs into which data is embedded!! And my intent is to make everything even safer by interacting with the underlying planning software as minimally as possible. I want this new program to be as close to a strict reader of planning system output as I can make it and do ALL processing and display of the data external to the planning system. Especially as every time the planning system software is upgraded it seems to come with a new set of its own bugs. And if it comforts anyone, if anyone asked me to write software that would directly control, interact with or potentially alter a patient's *actual* treatment, I would refuse point blank--even if it cost me my job-- because I know that my current knowledge and skill sets could not safely accomplish such a project. I do not know if I actually needed to say any of the above, but I feel better for having said it! ~(:>)) > There's nothing you can do about this; it's human nature. So I claim that > making sure the advice your program offers has > 1) few bugs. And what it has should be crashes, not just getting the > wrong result. > 2) Careful wording of the messages to indicate the confidence level of the > conclusion it's relating. Trying to do my very, very best! -- boB From robertvstepp at gmail.com Sun Apr 19 06:07:54 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 23:07:54 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: On Sat, Apr 18, 2015 at 10:03 PM, Bill Allen wrote: > > On Apr 18, 2015 4:11 PM, "boB Stepp" wrote: >> >> On Sat, Apr 18, 2015 at 3:28 PM, Bill Allen wrote: >> > On Apr 18, 2015 7:50 AM, "Peter Otten" <__peter__ at web.de> wrote: >> > >> >> Bill Allen wrote: [...] >> >> You can test your newfound knowledge by predicting the output of the >> >> following script: >> >> >> >> >> >> a = [1, ["x", "y"], 3] >> >> b = a[:] >> >> >> >> a[1][1] = "hello!" >> >> >> >> print(a) # [1, ['x', 'hello!'], 3] >> >> print(b) # what will that print? >> >> >> >> Think twice before you answer. What is copied, what is referenced? >> >> > print(b) will print the original copy of a which b now references which >> > is >> > [1, ["x", "y"], 3] >> >> Uh, oh! You should have checked your work in the interpreter before >> replying! Peter is being very tricky!! (At least for me...) Look again >> at that list inside of a list and... [...] > Ok, just tried it out. In this example b=a and b=a[:] seem to yield the > same results even after the change to a, which I do not understand. Should > not b be a copy of a and not reflect the change? Like you, I am on the path to learning Python, so I may or may not get all the technical details correct, but here goes (I'm certain that if I take any misstepps --pun intended!--that the ever-helpful crew of professionals will set us both straight): So far the emphasis on your original question has been on the differences between 'references to objects' and the actual 'objects'. I think that for the purpose of your question you can think about 'objects' as some sort of data stored someplace, though this is not technically correct. When an item of data is stored, it is more efficient to store it once and then from that point on use identifiers (Which we are used to thinking of in most instances as 'variables'.) to point to the storage location of that particular item of data. So when you originally said something like: my_list = ['a', 'b', 'c'] The ['a', 'b', 'c'] is the item of data stored and my_list is the identifier identifying *where* this particular item of data is stored. If you then do things like say: some_other_identifier = my_list then you just created a new identifier which gives the same location information to exactly the same piece of data. However, fortunately (Or, unfortunately, depending on your point of view.) you picked a type of data -- a list -- that is *mutable*. Like mutations in genetics, this just means that this item of data is capable of being changed in place, i.e., where it is actually stored in memory. So if Peter had said instead something like (Using the above statements.): some_other_identifier[1] = 'Hello!' I think you understand now that the originally *identified* list would now be ['a', 'Hello!', 'c'] . But Peter's actual example had a list inside of a list and BOTH of these are objects (In our discussion, items of data.) and BOTH of these have this property of being *mutable*. So he stuck an object inside of another object, so to speak. And this inner object has identifiers associated with it, too! Before Peter changed one of these changeable objects, he had: a = [1, ["x", "y"], 3] b = a[:] Now BOTH a[1] and b[1] now identify the location of the inner list object, ["x", "y"] . Apparently, Python, in its ever efficient memory management fashion, when it creates the new object/piece of data a[:], it sees no need to duplicate the inner list object, ["x", "y"], but instead creates another identifier/pointer/reference to this object's location. But since this inner list object is mutable, when you change "y" to "hello!" in b, you also change it in a because both a[1][1] and b[1][1] reference/point to the exact same storage location where this element of the inner list is actually stored. I hope this is helpful, and, if there are any misstepps, that when they are revealed both of our understandings will be enhanced! boB Stepp From cs at zip.com.au Sun Apr 19 06:08:06 2015 From: cs at zip.com.au (Cameron Simpson) Date: Sun, 19 Apr 2015 14:08:06 +1000 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: <20150419040806.GA80371@cskk.homeip.net> On 18Apr2015 22:03, Bill Allen wrote: >On Apr 18, 2015 4:11 PM, "boB Stepp" wrote: >> On Sat, Apr 18, 2015 at 3:28 PM, Bill Allen wrote: >> > On Apr 18, 2015 7:50 AM, "Peter Otten" <__peter__ at web.de> wrote: >> >> You can test your newfound knowledge by predicting the output of the >> >> following script: >> >> >> >> a = [1, ["x", "y"], 3] >> >> b = a[:] >> >> >> >> a[1][1] = "hello!" >> >> >> >> print(a) # [1, ['x', 'hello!'], 3] >> >> print(b) # what will that print? >> >> >> >> Think twice before you answer. What is copied, what is referenced? >> >> > print(b) will print the original copy of a which b now references which >is >> > [1, ["x", "y"], 3] >> >> Uh, oh! You should have checked your work in the interpreter before >> replying! Peter is being very tricky!! (At least for me...) Look again >> at that list inside of a list and... [...] > >Ok, just tried it out. In this example b=a and b=a[:] seem to yield the >same results even after the change to a, which I do not understand. Should >not b be a copy of a and not reflect the change? Because is it a _shallow_ copy. Doing this: b = a[:] produces a new list, referenced by "b", with the _same_ references in it as "a". a[1] is a reference to this list: ["x", "y"] b[1] is a reference to the _same_ list. So "a[:]" makes what is called a "shallow" copy, a new list with references to the same deeper structure. So this: a[1][1] = "hello!" affects the original x-y list, and both "a" and "b" reference it, so printing either shows the change. By contrast, this: a[1] = ["x", "hello"] _replaces_ the reference in "a" with a reference to a new, different, list. Sometimes you want a "deep" copy, where "b" would have got a copy of the iriginal x-y list. See the "copy" module's "deepcopy" function, which supplies this for when it is needed: https://docs.python.org/3/library/copy.html#copy.deepcopy Cheers, Cameron Simpson Draw little boxes with arrows. It helps. - Michael J. Eager From robertvstepp at gmail.com Sun Apr 19 06:26:02 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 18 Apr 2015 23:26:02 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: <20150419040806.GA80371@cskk.homeip.net> References: <20150419040806.GA80371@cskk.homeip.net> Message-ID: On Sat, Apr 18, 2015 at 11:08 PM, Cameron Simpson wrote: > Sometimes you want a "deep" copy, where "b" would have got a copy of the > iriginal x-y list. See the "copy" module's "deepcopy" function, which > supplies this for when it is needed: > > https://docs.python.org/3/library/copy.html#copy.deepcopy In this reference, part of it states: "Two problems often exist with deep copy operations that don?t exist with shallow copy operations: Recursive objects (compound objects that, directly or indirectly, contain a reference to themselves) may cause a recursive loop. Because deep copy copies everything it may copy too much, e.g., administrative data structures that should be shared even between copies." If I am understanding things correctly, should not that last sentence read instead: "...structures that should *not* be shared even between copies." ??? -- boB From cs at zip.com.au Sun Apr 19 07:09:51 2015 From: cs at zip.com.au (Cameron Simpson) Date: Sun, 19 Apr 2015 15:09:51 +1000 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: <20150419050951.GA40934@cskk.homeip.net> On 18Apr2015 23:26, boB Stepp wrote: >On Sat, Apr 18, 2015 at 11:08 PM, Cameron Simpson wrote: >> Sometimes you want a "deep" copy, where "b" would have got a copy of the >> iriginal x-y list. See the "copy" module's "deepcopy" function, which >> supplies this for when it is needed: >> >> https://docs.python.org/3/library/copy.html#copy.deepcopy > >In this reference, part of it states: > >"Two problems often exist with deep copy operations that don?t exist >with shallow copy operations: > >Recursive objects (compound objects that, directly or indirectly, >contain a reference to themselves) may cause a recursive loop. >Because deep copy copies everything it may copy too much, e.g., >administrative data structures that should be shared even between >copies." > >If I am understanding things correctly, should not that last sentence >read instead: > >"...structures that should *not* be shared even between copies." ??? No, the text is correct. Suppose you have a graph of objects where some single object A is referenced in mulitple places: /--> O1 ----v G < A \--> O2 ----^ If I make a deepcopy of "G" I want this: /--> O1copy ----v Gcopy < Acopy \--> O2copy ----^ i.e. a _single_ copy "Acopy" of "A", again referenced from 2 places in the copied graph. Without deepcopy()'s object tracking you would get something like this: /--> O1copy ----> Acopy1 Gcopy < \--> O2copy ----> Acopy2 i.e. two distinct copies of "A". Changes to "Acopy1" would not affect "Acopy2". Cheers, Cameron Simpson They said it couldn't be done/they said nobody could do it/ But he tried the thing that couldn't be done!/He tried - and he couldn't do it. From cs at zip.com.au Sun Apr 19 07:24:07 2015 From: cs at zip.com.au (Cameron Simpson) Date: Sun, 19 Apr 2015 15:24:07 +1000 Subject: [Tutor] lists, name semantics In-Reply-To: <20150419050951.GA40934@cskk.homeip.net> References: <20150419050951.GA40934@cskk.homeip.net> Message-ID: <20150419052407.GA63795@cskk.homeip.net> On 19Apr2015 15:09, Cameron Simpson wrote: >On 18Apr2015 23:26, boB Stepp wrote: >>On Sat, Apr 18, 2015 at 11:08 PM, Cameron Simpson wrote: >>>Sometimes you want a "deep" copy, where "b" would have got a copy of the >>>iriginal x-y list. See the "copy" module's "deepcopy" function, which >>>supplies this for when it is needed: >>> >>> https://docs.python.org/3/library/copy.html#copy.deepcopy >> >>In this reference, part of it states: >> >>"Two problems often exist with deep copy operations that don?t exist >>with shallow copy operations: >> >>Recursive objects (compound objects that, directly or indirectly, >>contain a reference to themselves) may cause a recursive loop. >>Because deep copy copies everything it may copy too much, e.g., >>administrative data structures that should be shared even between >>copies." >> >>If I am understanding things correctly, should not that last sentence >>read instead: >> >>"...structures that should *not* be shared even between copies." ??? > >No, the text is correct. Um, my explaination was incomplete. The first sentence quoted explains why it is necessary for deepcopy keep track of copied objects in order to correctly duplicate objects just once instead of twice or more, let alone in an unbounded way if there is a loop (A->B->C->A). It does this with a "memo" dictionary of already copied objects so it can know them when it sees them again. The second sentence "Because deep copy copies everything it may copy too much, e.g., administrative data structures that should be shared even between copies" is an issuewhich is addressed lower down when mentioning the __copy_ and __deepcopy__ methods. And it is not necessarily obvious. Suppose you've got a data structure of objects, which should broadly be copied. However, _internally_, these objects may use some external facility. Further, suppose that facility can't be copied; perhaps it is a reference to a databse or something built around something like that. Like this: G -> A -> B -> _open_database When you deepcopy that data sctructure you want to copy everything, but _not_ copy the external facility object. So for the above example, after the deepcopy you want this: Gcopy -> Acopy -> Bcopy -> _open_database i.e. the same reference to the database, but copies of "A" and "B". If you give "G"'s class a .__deepcopy__ method, then that will be called by deepcopy() to make a copy of "G" by calling "G.__deepcopy__(memodict)". And G's class will define its __deepcopy__ method to copy "A" and "B" but not "_open_database". Most classes do not need this and deepcopy() just copies everything. Does this clarify things? Cheers, Cameron Simpson No wonder these courtroom dramas are so popular. Half the population are lawyers, judges, or some other kind of criminal. - Jake Vest 1986 From cybervigilante at gmail.com Sun Apr 19 03:56:41 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 18 Apr 2015 18:56:41 -0700 Subject: [Tutor] sample dictionairies Message-ID: Where could I download Python sample dictionaries on different subjects. They're hard to type and I can only do small, limited ones to practice with. -- Jim The probability of a piano falling on my head is 50%. After it falls on my head the probability is 100%. My confidence in the piano hitting my head has increased. This is Bayesian statistics in a nutshell. From ben+python at benfinney.id.au Sun Apr 19 10:28:28 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Sun, 19 Apr 2015 18:28:28 +1000 Subject: [Tutor] sample dictionairies References: Message-ID: <85383wr07n.fsf@benfinney.id.au> Jim Mooney writes: > Where could I download Python sample dictionaries on different > subjects. I don't know what yoy mean by the ?subject? of a dictionary. A Python dict is a data structure. Its values can be any collection of Python objects. Is the ?subject? of a dictionary its meaning? Its meaning is entirely up to whoever wrote it and whoever reads it. So I have to guess that you mean something else. What do you mean by ?dictionaries on different subjects?? -- \ ?Technology is neither good nor bad; nor is it neutral.? | `\ ?Melvin Kranzberg's First Law of Technology | _o__) | Ben Finney From alan.gauld at btinternet.com Sun Apr 19 10:45:00 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 19 Apr 2015 09:45:00 +0100 Subject: [Tutor] sample dictionairies In-Reply-To: References: Message-ID: On 19/04/15 02:56, Jim Mooney wrote: > Where could I download Python sample dictionaries on different subjects. Like Ben I don't understand what you mean by subject. However,... > They're hard to type and I can only do small, limited ones to practice with. If you just want a large dictionary grab a plain text ebook(*) and write a short bit of code to extract all the unique words into a list. Then iterate over that list and create a dictionary using the words as keys and their length as values. If you start with something like the bible then that should give you a reasonably big dictionary for relatively little typing. (*) Project Gutenberg has dozens of free examples. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Sun Apr 19 12:42:46 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 19 Apr 2015 20:42:46 +1000 Subject: [Tutor] sample dictionairies In-Reply-To: References: Message-ID: <20150419104246.GB5663@ando.pearwood.info> On Sat, Apr 18, 2015 at 06:56:41PM -0700, Jim Mooney wrote: > Where could I download Python sample dictionaries on different subjects. > They're hard to type and I can only do small, limited ones to practice with. I don't think you can download Python dicts. It would be a bit hard, since Python dicts exist only while the Python interpreter is running. Normally data is provided in text form, and then read from a file and converted into a dict or list as needed. If you search the internet, you will find lots of places that you can download data on various topics. You can start at Wikidata: https://www.wikidata.org/ ?http://en.wikipedia.org/wiki/Wikidata But for simple experiments, there is an easier solution. Instead of typing the dicts yourself, create them programmatically! Let's say I want a dict like: {'a': 1, 'b': 2, 'c': 3, ... 'z': 26} That would be a PITA to type out in full. But I can do this: import string pairs = zip(string.ascii_lowercase, range(1, 27)) d = dict(pairs) zip is invaluable for this sort of thing, because it takes two (or more) independent sequences and "zips" them together into a single sequence of pairs. So zip('abcde...z', [1, 2, 3, 4, 5, ..., 26]) ends up as the sequence [('a', 1), ('b', 2), ('c', 3), ... ] which is exactly what dict() needs to build a dictionary. Here's another example: from random import random d = dict((n, random()) for n in range(10000)) This uses a *generator expression* to provide a sequence of (key, value) pairs, where the keys are numbers 0, 1, 2, ... and the values are random floats. You might have seen list comprehensions: [x**2+1 for x in range(15)] for example. Generator expressions are similar, except they don't calculate the items up front into a list, they calculate them lazily only when needed. To turn a list comprehension into a generator expression, change the outer-most square brackets [ ] into round brackets: (x**2+1 for x in range(15)) In Python 3, we also have *dict comprehensions* which are based on list comprehensions: d = {n: random() for n in range(10000)} So my advice is this: rather than look for somebody to provide you with ready-made dicts, learn how to assemble them yourself! # dict of {name: age} pairs names = 'Fred Wilma Barney Betty Homer Marge'.split() ages = [35, 31, 34, 36, 30] d = dict(zip(name, ages)) -- Steve From davea at davea.name Sun Apr 19 13:47:59 2015 From: davea at davea.name (Dave Angel) Date: Sun, 19 Apr 2015 07:47:59 -0400 Subject: [Tutor] lists, name semantics In-Reply-To: References: Message-ID: <553395EF.3020708@davea.name> On 04/19/2015 12:07 AM, boB Stepp wrote: ..... Before Peter changed one of these > changeable objects, he had: > > a = [1, ["x", "y"], 3] > b = a[:] > > Now BOTH a[1] and b[1] now identify the location of the inner list > object, ["x", "y"] . Apparently, Python, in its ever efficient memory > management fashion, when it creates the new object/piece of data > a[:], it sees no need to duplicate the inner list object, ["x", "y"], > but instead creates another identifier/pointer/reference to this > object's location. But since this inner list object is mutable, when > you change "y" to "hello!" in b, you also change it in a because both > a[1][1] and b[1][1] reference/point to the exact same storage location > where this element of the inner list is actually stored. > > I hope this is helpful, and, if there are any misstepps, that when > they are revealed both of our understandings will be enhanced! > Some of your knowledge of other languages is leaking into your explanation. When we talk of the language Python, we need to distinguish between how CPython happens to be implemented, how other Python implementations happen to be created, and how C++ (for example) implements similar things. Some of the above use pointers, some do not. The language Python does not. So especially when talking of inner lists, we need to clarify a few things. An object has an identity, not a location. That identity can be checked with the 'is' operator, or the id() function. But it exists all the time. Variables, as you say, do not contain an object, they reference it. And the formal term for that is binding. A name is bound to an object, to one object, at a time. Now some objects have attributes, which is to say names, and those attributes are bound to other objects. So if we define a class, and have an instance of that class, and the instance has attributes, we can do something like: obj.inst_name and get the particular attribute. Still other objects have unnamed bindings. The canonical example is a list. A list object has a bunch of bindings to other objects. Even though each binding doesn't have a specific name, it nevertheless exists. And in this case we use integers to specify which of those bindings we want to follow. And we use a special syntax (the square bracket) to indicate which of these we want. So let's take the simplest example: mylist = ["a", "b"] the name mylist is bound to a list object, which has two numbered bindings, called 0 and 1. That object's [0] binding is to a separate object "a". And the [1] binding is to a separate object "b" There is another shorthand called a slice, which looks like [start, len, step] which lets us construct a *new* list from our list. And using defaults for all three terms lets us copy the list. But let's look at what the copy means: newlist = mylist[:] --> mylist[0, 2, 1] This constructs a new list from the present one, where the zeroth location is bound to whatever object the first list's zeroth location was bound to. And so on for the oneth location, the twoth, etc. Only one new list object is built, and no new objects are made for it. It just gets new bindings to the same things the first list had. At this point, it should be clear what a shallow copy means. If the original list's oneth item was a binding to another list object, *that* list object does NOT get copied. I don't like the term "inner list", but I don't know if it's incorrect. It's just misleading, since to the slice operation, the fact that it's a list is irrelevant. It's just an object whose binding is to be copied. -- DaveA From lac at openend.se Sun Apr 19 10:16:24 2015 From: lac at openend.se (Laura Creighton) Date: Sun, 19 Apr 2015 10:16:24 +0200 Subject: [Tutor] sample dictionairies In-Reply-To: Message from Jim Mooney of "Sat, 18 Apr 2015 18:56:41 -0700." References: Message-ID: <201504190816.t3J8GOho021852@fido.openend.se> In a message of Sat, 18 Apr 2015 18:56:41 -0700, Jim Mooney writes: >Where could I download Python sample dictionaries on different subjects. >They're hard to type and I can only do small, limited ones to practice with. > >-- >Jim For randomly generating data which look like addresses, I use: http://www.generatedata.com/ While it has 'export to programming language' as a feature, Python isn't one of the supported languages. Which is fine. It can export into comma separated values, and writing a Python program to construct a dictionary from comma separated values is easy. Laura From niyanaxx95 at gmail.com Sun Apr 19 17:25:59 2015 From: niyanaxx95 at gmail.com (niyanaxx95 at gmail.com) Date: Sun, 19 Apr 2015 15:25:59 +0000 Subject: [Tutor] =?utf-8?q?=3DLinked_List_Using_Map?= In-Reply-To: <20150419030232.GA5663@ando.pearwood.info> References: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> <55314cc2.9512370a.1868.ffffd2c5@mx.google.com>, <20150419030232.GA5663@ando.pearwood.info> Message-ID: <5533c98c.0514370a.2a4e.0d96@mx.google.com> Thank You Steven for your great help!!!! You really helped me to understand my assignment more as well as what maps and linked lists are. I used your guidance and came up with my full code. May you take a look and let me know what needs to be changed? Thank you in advance. class Node: def __init__( self, key, value, next = None ) : self.key = key self.value = value self.next = next def getItem( self ) : return self.key def getNext( self ) : return self.next def setItem( self, item ) : self.next = next def setNext( self, next ) : self.next = next class Map: def __init__( self, contents = []) : self.first = None self.last = self.first self.numItems = 0 # traverse the linked list node = self.first while node is not None: print("key = %s, value = %s" % (node.key, node.value)) node = node.next # Add new node to the end node = self.first if node is None: self.first = Node("the key", "some value") else: while node.next is not None: node = node.next node.next = Node("the key", "some value") def length( self ) : if node.next == Node("the key", "some value"): self.numItems = self.numItems + 1 else: self.numItems = self.numItems - 1 return self.numItems def contains() : node = self.first while node is not None: if node.key == key: return True else: return False def setitem( self, key, value ) : node = self.first while node is not None: if key in self.key : pos = self.key.index(key) node.value[pos] = value return else: node = node.next def getitem( self, key ) : node = self.first while node is not None: assert key in self.key keypos = self.key.index(key) return node.value[keypos] # Clears or empties the map by removing all key/value pairs def clear( self ): return self.first == None # Returns a list containing the keys stored in the map. def keys( self ): return self.key # Returns a list contain the values stored in the map. def values( self ): return self.value # Returns a string representation of the map in the following format:{k1:v1, k2:v2, ..., kN:vN} def __repr__( self ): return "{%s}" % (", ".join(["%s:%s" % (k,v) for k, v in zip(self._key, self._value)])) # Returns the minimum key in the map. The map cannot be empty. def min(self, key ): node = self.first while node is not None and self.first == None: pass # Returns the maxiumum key in the map. The map cannot be empty. def max( self, key ): node = self.first while node is not None and self.first == None: pass # Create a new linked list that contains the same entries as the origninal def copy( self ): if self.next is None: return self.value else: return self.value, self.next.copy() Sent from Windows Mail From: Steven D'Aprano Sent: ?Saturday?, ?April? ?18?, ?2015 ?11?:?02? ?PM To: tutor at python.org Cc: Ni'Yana Morgan Hello Ni'Yana, and welcome! On Fri, Apr 17, 2015 at 06:11:00PM +0000, niyanaxx95 at gmail.com wrote: > Hello I need guidance trying to solve my assignment. I am completely > lost when using maps with linked lists. I understand linked lists > though. May someone work with me? We will not do your homework, but perhaps we can guide you. Thank you for showing your code. It looks like you have already made a lot of progress. Unfortunately, the one thing you did not tell us is what part of the assignment you are having problems with! It looks like you have done most of the work correctly so far, so what part is giving you trouble? A few comments on your code below: > class Node: > def __init__( self, item, next = None ) : > self.item = item > self.next = next > def getItem( self ) : > return self.item > def getNext( self ) : > return self.next > def setItem( self, item ) : > self.item = item > def setNext( self, next ) : > self.next = next Your Node class looks straightforward, but it doesn't match the requirements. The requirement for the Map is that it must have key:value pairs. But your Node doesn't have two data fields, it only has one! So you cannot give the Node both a key and a value. Your Node class needs to start like this: class Node: def __init__(self, key, value, next=None): self.key = key self.value = value self.next = next That will help get the Map class right. See my comments below. > class Map: > def __init__( self, contents = []) : > self.first = LinkedList.Node(None, None) First problem: you have added code which is not part of the specifications. The assignment says that calling Map() returns a new empty map. It says nothing about Map([1, 2, 3]). Get rid of the "contents" argument, it is not required. Once you get rid of that, the "for e in contents" loop is not required. Get rid of it! Second problem: LinkedList is not defined anywhere. What is it? The easiest way for this to work is to put the None class and the Map class in the same file, and then you can just say: self.first = Node(None, None) without worrying about the name of the file. Java has a rule that each class, no matter how tiny, must go in its own file, but Python does not have such a rule. Related classes may go in the same file. Third problem: your assignment to self.first is wrong! That gives the Map a single item, not zero items! An empty linked list will be represented here by just None alone. self.first = None You then traverse the linked list like this: node = self.first while node is not None: print("key = %s, value = %s" % (node.key, node.value)) node = node.next which will print all the keys and values in the map. To add a new node to the end, you do this: node = self.first # The empty Map case is special. if node is None: self.first = Node("the key", "some value") else: while node.next is not None: node = node.next # Now we are at the end of the linked list. # Add a new node. node.next = Node("the key", "some value") > self.last = self.first > self.numItems = 0 > for e in contents: > self.append(e) > > def __len__( self ) : > count = 0 > while self != None: > count +=1 > self = self.next > return count I don't think that this will do what your assignment asks. The first problem is that your assignment says that your Map must have a method called `length` which returns the number of items. Your Map class has no method called `length`, instead it uses the Python special __len__ method. I think you need to change the name of this __len__ method to length. It is still be buggy (have you tested it?) but at least it will do what the assignment says. Let us think about how to implement this length method. It is actually very easy! Your Map class already has a counter which tell you how many items are in the map, and it is initialised with: self.numItems = 0 so length is easy: def length(self): return self.numItems Now all you need to do is make sure that every time you add a node to the Map, add 1 to numItems, and every time you delete a node, you subtract 1. > def contains() : > pass I assume this is just a stub which is not finished yet. The contains method just needs to walk the linked list and look for the key. I showed you code above that walks the linked list printing keys and values. Instead of printing, you compare the node's key to the key you are looking for, and if they are equal, return True: while node is not None: if node.key == key: return True If you reach the end of the linked list without finding the key, you have to return False. Both your __setitem__ and __getitem__ methods also ignore what the assignment says. The assignment wants methods called `setitem` and `getitem`, not the special Python double-underscore methods. So you need to change their names, then test them. Also, they fail to do what the assignment says. Read the requirements: getitem(key): Returns the value associated with the given key, which must exist. Does your __getitem__ method take a key as argument? No it does not, it takes an index! getitem needs to take a single argument, the key. It then walks the linked list (as I showed you above), comparing the node's key to the wanted key. If they are equal, you then return node.value. If they are not equal, go on to the next node. If you run out of nodes before finding the key, that is an error. setitem needs to take two arguments, a key and a value. You then walk the linked list (again!) and compare the node's key to the wanted key. If they are equal, you set the node's value to the new value: node.value = value and return. If you run out of nodes, you add a new node at the end. Remember what I said about incrementing the counter! By this time, you should see a pattern. Nearly all these methods demonstrate the same sort of procedure: you walk the linked list, looking at each node in turn: node = self.first while node is not None: do_something_with(node) -- Steve From alan.gauld at btinternet.com Sun Apr 19 20:18:43 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 19 Apr 2015 19:18:43 +0100 Subject: [Tutor] =Linked List Using Map In-Reply-To: <5533c98c.0514370a.2a4e.0d96@mx.google.com> References: <55314ca1.c7628c0a.6f1c.ffffd77a@mx.google.com> <55314cc2.9512370a.1868.ffffd2c5@mx.google.com>, <20150419030232.GA5663@ando.pearwood.info> <5533c98c.0514370a.2a4e.0d96@mx.google.com> Message-ID: On 19/04/15 16:25, niyanaxx95 at gmail.com wrote: > May you take a look and let me know what needs to be changed? Thank you in advance. The node code looks OK. > class Map: > Read through your init method, remembering that it only gets calledv once when the Map is created. > def __init__( self, contents = []) : > self.first = None > self.last = self.first > self.numItems = 0 So far so good. > # traverse the linked list But there is no list at this point. You just set it to None. > node = self.first > while node is not None: > print("key = %s, value = %s" % (node.key, node.value)) > node = node.next So that block does nothing. > # Add new node to the end > node = self.first > if node is None: And you know the node is NBone so you don;t need a test > self.first = Node("the key", "some value") This is the only meaningful line in the method so far. Although I suspect the key and value need to be fetched from somewhere so that they are useful. Also shouldn't you increment the numItems counter about now? > else: > while node.next is not None: > node = node.next > node.next = Node("the key", "some value") This else block never gets executed either since the node is always None. Most of the init method can be deleted. > def length( self ) : > if node.next == Node("the key", "some value"): > self.numItems = self.numItems + 1 > else: > self.numItems = self.numItems - 1 > return self.numItems This is just wrong. You keep incrementing numItems but never reset it. Also you keep creating a new Node then throwing it away. If you keep numItems up to date as you add and delete items all you need do is return nnumItems. > def contains() : > node = self.first > while node is not None: > if node.key == key: > return True where does key come from? I assume it should be a parameter of the method? > else: > return False Thids returns False after the first test. What if the node you are looking for is further down the list? You need to exdent (dedent?) this section till its outside the while loop. > def setitem( self, key, value ) : > node = self.first > while node is not None: > if key in self.key : Where does self.key come from? Its not set in the init() method. Also if its a collection shouldn't it be called keys? > pos = self.key.index(key) > node.value[pos] = value > return If pos is the index into the list of keys I assume valyue should be a corresponding list of values? In which case call it values not value. But if you are using a ppair of lists to hold the keys and values what is the linked list of nodes for? They seem pointless. But the value(s) dseem to be attached to the node? But the keys are attached tgto the Maop(self)? I'm not sure what you are trying to do here. > else: > node = node.next > > def getitem( self, key ) : > node = self.first > while node is not None: > assert key in self.key > keypos = self.key.index(key) > return node.value[keypos] The while loop only goes as far as the first node. Does every node contain a list of all the values? That seems a bit wasteful? > # Clears or empties the map by removing all key/value pairs > def clear( self ): > return self.first == None This returns a boolean result. Which is not what the comment says it does. > # Returns a list containing the keys stored in the map. > def keys( self ): > return self.key > > # Returns a list contain the values stored in the map. > def values( self ): > return self.value But the values were attacheed to the nodes not self? > # Returns a string representation of the map in the following format:{k1:v1, k2:v2, ..., kN:vN} > def __repr__( self ): > return "{%s}" % (", ".join(["%s:%s" % (k,v) for k, v in zip(self._key, self._value)])) > > > # Returns the minimum key in the map. The map cannot be empty. > def min(self, key ): > node = self.first > while node is not None and self.first == None: > pass If you set node to be self.first how can they be different as required by your while loop test? > # Returns the maxiumum key in the map. The map cannot be empty. > def max( self, key ): > node = self.first > while node is not None and self.first == None: > pass As above > # Create a new linked list that contains the same entries as the origninal > def copy( self ): > if self.next is None: > return self.value > else: > return self.value, self.next.copy() This is returning a tuple not a copy of the original. Can I suggest you try running your code before posting it. That way you either have a set of error messages that you don't understand how to fix, or you fix things so they run but it doesn't quite do what you want. We call this testing in the trade and it's a really good idea. In fact its a good idea to build your classes one method at a time and test it until that one works before even trying to write the other methods. That way you know where the faults lie - in the code you just wrote! There are all sorts of fancy testing tools you can use, but just starting the >>> interactive prompt, importing your class file, creating some instances and calling the methods with different values is a great starting point! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Sun Apr 19 20:36:08 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 19 Apr 2015 13:36:08 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: <20150419052407.GA63795@cskk.homeip.net> References: <20150419050951.GA40934@cskk.homeip.net> <20150419052407.GA63795@cskk.homeip.net> Message-ID: On Sun, Apr 19, 2015 at 12:24 AM, Cameron Simpson wrote: > On 19Apr2015 15:09, Cameron Simpson wrote: >> >> On 18Apr2015 23:26, boB Stepp wrote: >>> >>> On Sat, Apr 18, 2015 at 11:08 PM, Cameron Simpson wrote: [...] >>> "Two problems often exist with deep copy operations that don?t exist >>> with shallow copy operations: >>> >>> Recursive objects (compound objects that, directly or indirectly, >>> contain a reference to themselves) may cause a recursive loop. >>> Because deep copy copies everything it may copy too much, e.g., >>> administrative data structures that should be shared even between >>> copies." >>> >>> If I am understanding things correctly, should not that last sentence >>> read instead: >>> >>> "...structures that should *not* be shared even between copies." ??? >> >> >> No, the text is correct. > > > Um, my explaination was incomplete. [...] > The second sentence "Because deep copy copies everything it may copy too > much, e.g., administrative data structures that should be shared even > between copies" is an issuewhich is addressed lower down when mentioning the > __copy_ and __deepcopy__ methods. And it is not necessarily obvious. > > Suppose you've got a data structure of objects, which should broadly be > copied. However, _internally_, these objects may use some external > facility. Further, suppose that facility can't be copied; perhaps it is a > reference to a databse or something built around something like that. Like > this: > > G -> A > -> B > -> _open_database > > When you deepcopy that data sctructure you want to copy everything, but > _not_ copy the external facility object. So for the above example, after the > deepcopy you want this: > > Gcopy -> Acopy > -> Bcopy > -> _open_database > > i.e. the same reference to the database, but copies of "A" and "B". Ah! This example clarifies things for me. This provides a specific context for the phrase, "...that should be shared even between copies..." That now makes sense. > If you give "G"'s class a .__deepcopy__ method, then that will be called by > deepcopy() to make a copy of "G" by calling "G.__deepcopy__(memodict)". And > G's class will define its __deepcopy__ method to copy "A" and "B" but not > "_open_database". > > Most classes do not need this and deepcopy() just copies everything. > > Does this clarify things? Very much! Thanks! -- boB From robertvstepp at gmail.com Sun Apr 19 21:08:41 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 19 Apr 2015 14:08:41 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: <553395EF.3020708@davea.name> References: <553395EF.3020708@davea.name> Message-ID: On Sun, Apr 19, 2015 at 6:47 AM, Dave Angel wrote: > On 04/19/2015 12:07 AM, boB Stepp wrote: [...] >> I hope this is helpful, and, if there are any misstepps, that when >> they are revealed both of our understandings will be enhanced! >> > > Some of your knowledge of other languages is leaking into your explanation. > When we talk of the language Python, we need to distinguish between how > CPython happens to be implemented, how other Python implementations happen > to be created, and how C++ (for example) implements similar things. Some of > the above use pointers, some do not. The language Python does not. I actually was being deliberately *imprecise* in my use of technical terminology. But I see below that there are some nuances I need to learn... > So especially when talking of inner lists, we need to clarify a few things. > > An object has an identity, not a location. That identity can be checked > with the 'is' operator, or the id() function. But it exists all the time. But the object, in order to exist, must be stored in RAM somewhere, doesn't it? Or is the real point that we are adding an abstraction layer so we don't even have to think about where objects are physically stored in RAM? So I am the object referenced by "boB" and we don't care what my precise (x, y, z) coordinates are relative to the planet Earth. If we need to find me or modify me we use my label, "boB", to access me? > Variables, as you say, do not contain an object, they reference it. And the > formal term for that is binding. A name is bound to an object, to one > object, at a time. > > Now some objects have attributes, which is to say names, and those > attributes are bound to other objects. So if we define a class, and have an > instance of that class, and the instance has attributes, we can do something > like: > obj.inst_name > > and get the particular attribute. > > Still other objects have unnamed bindings. The canonical example is a list. > A list object has a bunch of bindings to other objects. Even though each > binding doesn't have a specific name, it nevertheless exists. And in this > case we use integers to specify which of those bindings we want to follow. > And we use a special syntax (the square bracket) to indicate which of these > we want. Ah, "unnamed bindings" was the concept I was talking around. I realized these were there and were referenced by the square bracket syntax, but I did not know what to call the concept. [...] > At this point, it should be clear what a shallow copy means. If the > original list's oneth item was a binding to another list object, *that* list > object does NOT get copied. > > I don't like the term "inner list", but I don't know if it's incorrect. > It's just misleading, since to the slice operation, the fact that it's a > list is irrelevant. It's just an object whose binding is to be copied. So the real point here is that there are two distinct copying mechanisms, deep and shallow. The "inner list" could just have been any other type of object, though if it had been an immutable type it would not have made Peter's original interesting point. -- boB From davea at davea.name Sun Apr 19 23:05:23 2015 From: davea at davea.name (Dave Angel) Date: Sun, 19 Apr 2015 17:05:23 -0400 Subject: [Tutor] lists, name semantics In-Reply-To: References: <553395EF.3020708@davea.name> Message-ID: <55341893.9020600@davea.name> On 04/19/2015 03:08 PM, boB Stepp wrote: > On Sun, Apr 19, 2015 at 6:47 AM, Dave Angel wrote: >> On 04/19/2015 12:07 AM, boB Stepp wrote: > > [...] > >>> I hope this is helpful, and, if there are any misstepps, that when >>> they are revealed both of our understandings will be enhanced! >>> >> >> Some of your knowledge of other languages is leaking into your explanation. >> When we talk of the language Python, we need to distinguish between how >> CPython happens to be implemented, how other Python implementations happen >> to be created, and how C++ (for example) implements similar things. Some of >> the above use pointers, some do not. The language Python does not. > > I actually was being deliberately *imprecise* in my use of technical > terminology. But I see below that there are some nuances I need to > learn... > >> So especially when talking of inner lists, we need to clarify a few things. >> >> An object has an identity, not a location. That identity can be checked >> with the 'is' operator, or the id() function. But it exists all the time. > > But the object, in order to exist, must be stored in RAM somewhere, > doesn't it? Or in a swap file, a disk file, or some other media. > Or is the real point that we are adding an abstraction > layer so we don't even have to think about where objects are > physically stored in RAM? Somebody keeps track, but the address is not necessarily constant, and not necessarily stored in any references. The references (bindings) are abstract, and the details are unimportant to the user. For example, the jython system does not use addresses at all. And an object gets moved around from time to time without its references knowing it. > So I am the object referenced by "boB" and > we don't care what my precise (x, y, z) coordinates are relative to > the planet Earth. If we need to find me or modify me we use my label, > "boB", to access me? No, we use one of your many labels to find you. And if no labels exist, you quietly cease to exist (garbage collection). But understand that a "label" in this sense need not be some alpha string. It might be a slot in some collection, like the way I described list. > >> Variables, as you say, do not contain an object, they reference it. And the >> formal term for that is binding. A name is bound to an object, to one >> object, at a time. >> >> Now some objects have attributes, which is to say names, and those >> attributes are bound to other objects. So if we define a class, and have an >> instance of that class, and the instance has attributes, we can do something >> like: >> obj.inst_name >> >> and get the particular attribute. >> >> Still other objects have unnamed bindings. The canonical example is a list. >> A list object has a bunch of bindings to other objects. Even though each >> binding doesn't have a specific name, it nevertheless exists. And in this >> case we use integers to specify which of those bindings we want to follow. >> And we use a special syntax (the square bracket) to indicate which of these >> we want. > > Ah, "unnamed bindings" was the concept I was talking around. I > realized these were there and were referenced by the square bracket > syntax, but I did not know what to call the concept. > > [...] > >> At this point, it should be clear what a shallow copy means. If the >> original list's oneth item was a binding to another list object, *that* list >> object does NOT get copied. >> >> I don't like the term "inner list", but I don't know if it's incorrect. >> It's just misleading, since to the slice operation, the fact that it's a >> list is irrelevant. It's just an object whose binding is to be copied. > > So the real point here is that there are two distinct copying > mechanisms, deep and shallow. The "inner list" could just have been > any other type of object, though if it had been an immutable type it > would not have made Peter's original interesting point. The distinction between deep and shallow was already made, by better people than I. I was trying to explain it in terms of a working model that would let you predict what will happen in each circumstance. A slice only copies the bindings in the list, it doesn't care what they are bound to. It's shallow because it's shallow. -- DaveA From robertvstepp at gmail.com Mon Apr 20 00:23:13 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 19 Apr 2015 17:23:13 -0500 Subject: [Tutor] lists, name semantics In-Reply-To: <55341893.9020600@davea.name> References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> Message-ID: On Sun, Apr 19, 2015 at 4:05 PM, Dave Angel wrote: > On 04/19/2015 03:08 PM, boB Stepp wrote: >> >> Or is the real point that we are adding an abstraction >> layer so we don't even have to think about where objects are >> physically stored in RAM? > > > Somebody keeps track, but the address is not necessarily constant, and not > necessarily stored in any references. The references (bindings) are > abstract, and the details are unimportant to the user. For example, the > jython system does not use addresses at all. And an object gets moved > around from time to time without its references knowing it. The last sentence in this paragraph has me intrigued. Why would an object, once it has been created, be moved? What practical benefit does doing this give? boB From joel.goldstick at gmail.com Mon Apr 20 00:28:56 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Sun, 19 Apr 2015 18:28:56 -0400 Subject: [Tutor] lists, name semantics In-Reply-To: References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> Message-ID: On Sun, Apr 19, 2015 at 6:23 PM, boB Stepp wrote: > On Sun, Apr 19, 2015 at 4:05 PM, Dave Angel wrote: >> On 04/19/2015 03:08 PM, boB Stepp wrote: >>> > >>> Or is the real point that we are adding an abstraction >>> layer so we don't even have to think about where objects are >>> physically stored in RAM? >> >> >> Somebody keeps track, but the address is not necessarily constant, and not >> necessarily stored in any references. The references (bindings) are >> abstract, and the details are unimportant to the user. For example, the >> jython system does not use addresses at all. And an object gets moved >> around from time to time without its references knowing it. > > The last sentence in this paragraph has me intrigued. Why would an > object, once it has been created, be moved? What practical benefit > does doing this give? > > boB I'm guessing memory management. You want to have large contiguous blocks of memory available for large objects. If a small object is surrounded by available memory, you might want to move it to some smaller empty spot. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From davea at davea.name Mon Apr 20 01:19:27 2015 From: davea at davea.name (Dave Angel) Date: Sun, 19 Apr 2015 19:19:27 -0400 Subject: [Tutor] lists, name semantics In-Reply-To: References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> Message-ID: <553437FF.7070803@davea.name> On 04/19/2015 06:28 PM, Joel Goldstick wrote: > On Sun, Apr 19, 2015 at 6:23 PM, boB Stepp wrote: >> On Sun, Apr 19, 2015 at 4:05 PM, Dave Angel wrote: >>> On 04/19/2015 03:08 PM, boB Stepp wrote: >>>> >> >>>> Or is the real point that we are adding an abstraction >>>> layer so we don't even have to think about where objects are >>>> physically stored in RAM? >>> >>> >>> Somebody keeps track, but the address is not necessarily constant, and not >>> necessarily stored in any references. The references (bindings) are >>> abstract, and the details are unimportant to the user. For example, the >>> jython system does not use addresses at all. And an object gets moved >>> around from time to time without its references knowing it. >> >> The last sentence in this paragraph has me intrigued. Why would an >> object, once it has been created, be moved? What practical benefit >> does doing this give? >> >> boB > > I'm guessing memory management. You want to have large contiguous > blocks of memory available for large objects. If a small object is > surrounded by available memory, you might want to move it to some > smaller empty spot. Good answer. The java jvm garbage collector is free to move blocks around to defrag the free space. FWIW, I'm told the ID value used is a simple integer, that indexes a list containing the actual addresses. So in this case, the binding value is an integer, not an address. -- DaveA From lac at openend.se Mon Apr 20 00:52:40 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 20 Apr 2015 00:52:40 +0200 Subject: [Tutor] lists, name semantics In-Reply-To: Message from boB Stepp of "Sun, 19 Apr 2015 17:23:13 -0500." References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> Message-ID: <201504192252.t3JMqe5p022981@fido.openend.se> In a message of Sun, 19 Apr 2015 17:23:13 -0500, boB Stepp writes: >On Sun, Apr 19, 2015 at 4:05 PM, Dave Angel wrote: >> abstract, and the details are unimportant to the user. For example, the >> jython system does not use addresses at all. And an object gets moved >> around from time to time without its references knowing it. > >The last sentence in this paragraph has me intrigued. Why would an >object, once it has been created, be moved? What practical benefit >does doing this give? > >boB One great reason is called 'garbage collection'. We find all the objects we are using, stuff them someplace in memory, and free up all the space they left. Now we are free to lay down a whole lot of other things, in contiguous order. When you want to go access an array, for instance, it matters' a whole lot if you can actually say: for x for y tell_me (x,y) rather than a lot of 'oops, I would love to tell you but when I went to an address I got told, out space, go look over hear instead. From lac at openend.se Mon Apr 20 00:56:42 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 20 Apr 2015 00:56:42 +0200 Subject: [Tutor] lists, name semantics In-Reply-To: Message from boB Stepp of "Sun, 19 Apr 2015 17:23:13 -0500." References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> Message-ID: <201504192256.t3JMugI5023122@fido.openend.se> In a message of Sun, 19 Apr 2015 17:23:13 -0500, boB Stepp writes: >The last sentence in this paragraph has me intrigued. Why would an >object, once it has been created, be moved? What practical benefit >does doing this give? > boB If you have more than enough memory in your system, you never do this because there is never any need. But if you would like to lay down an array of x by y for the fastest access, you would like it to fit perfectly in memory. Which can mean that the best you can do is pick up a bunch of smaller objects, move them someplace (anyplace) else, and then let your bigger object fit in memory in contiguous space. See 'garbage collection' for more useful ideas. Laura From lac at openend.se Mon Apr 20 01:29:34 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 20 Apr 2015 01:29:34 +0200 Subject: [Tutor] lists, name semantics In-Reply-To: Message from Dave Angel of "Sun, 19 Apr 2015 19:19:27 -0400." <553437FF.7070803@davea.name> References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> <553437FF.7070803@davea.name> Message-ID: <201504192329.t3JNTYUa024447@fido.openend.se> In a message of Sun, 19 Apr 2015 19:19:27 -0400, Dave Angel writes: >Good answer. The java jvm garbage collector is free to move blocks >around to defrag the free space. Correct. >FWIW, I'm told the ID value used is a simple integer, that indexes a >list containing the actual addresses. Also correct for the majority of cases. You would have to be an expert in GC to care about when this is not correct, which is what I happen to be, but only a pedant would object to what you said. >So in this case, the binding value is an integer, not an address. Utterly wrong. The binding value has to be an address. All addresses are integers. I have no clue what you meant by this. Please resubmit and try again. That some of the adresses are indirectly referred to through a list means _nothing_. Very puzzled, your brain is thinking wrong thoughts, but mostly I can guess what is meant, here I cannot at all, Sorry about that, Laura From alan.gauld at btinternet.com Mon Apr 20 02:17:09 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 01:17:09 +0100 Subject: [Tutor] lists, name semantics In-Reply-To: <201504192329.t3JNTYUa024447@fido.openend.se> References: <553395EF.3020708@davea.name> <55341893.9020600@davea.name> <553437FF.7070803@davea.name> <201504192329.t3JNTYUa024447@fido.openend.se> Message-ID: On 20/04/15 00:29, Laura Creighton wrote: >> So in this case, the binding value is an integer, not an address. > > Utterly wrong. The binding value has to be an address. I think it depends on how you define 'binding' value. In Python binding is the connection between a name and an object. So in a handle type system the binding between a name and object is the objects handle, which is usually an integer. But the address of the object is the thing the VM uses to fetch the actual object based on the handle. So we have two bindings at work. The one the user sees between the name and the object (which is the handle) and the one the VM uses between the handle and the actual object, which is its address at that particular moment in time. Its the VMs job to keep track of how that second binding changes but the users view of binding (the handle) never changes. > All addresses are integers. Usually, but not always. In segmented architectures they are tuples of integers, and in clustered Virtual Memory implementations they may be vectors. But in modern machines they usually resolve to an integer. > I have no clue what you meant by this. Please resubmit > and try again. That some of the adresses are indirectly referred to > through a list means _nothing_. It means a huge amount to the user(programmer), especially if he/she erroneously tries to use a handle as an address. And of course there is a third layer of abstraction here because often times the "address" that compiler and VM writers think of as the physical address is nothing of the sort its just a bit of virtual space created by the OS which then does another binding to the real RAM chips (or magnetic tape, or optical drive or ferrite core or whatever technology is providing the physical storage) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Mon Apr 20 03:03:02 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 19 Apr 2015 20:03:02 -0500 Subject: [Tutor] OT: Is there a good book that covers the history/evolution of software? [Inspired by the thread: lists, name semantics] Message-ID: In the beginning (I assume.) there was machine code and only machine code. And I imagine this was not very good. Then I assume the next step was assembler, which probably only moderated the (then) tedium of coding. Then real high level languages were started to be developed, and this was very good. And then there were various new programming paradigms developed, and so on. What I am wondering is, is there a good book that covers in relatively good detail how we started at the most primitive level, machine code, and evolved to our current wonderful cornucopia of languages, operating systems, etc.? As the different threads reveal bits and pieces of the low level guts of Python, I am becoming more and more fascinated about how all of this is managed. Just the brief discussion of garbage collection details going on I find quite interesting. -- boB From joel.goldstick at gmail.com Mon Apr 20 03:26:08 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Sun, 19 Apr 2015 21:26:08 -0400 Subject: [Tutor] OT: Is there a good book that covers the history/evolution of software? [Inspired by the thread: lists, name semantics] In-Reply-To: References: Message-ID: On Sun, Apr 19, 2015 at 9:03 PM, boB Stepp wrote: > In the beginning (I assume.) there was machine code and only machine > code. And I imagine this was not very good. Then I assume the next > step was assembler, which probably only moderated the (then) tedium of > coding. Then real high level languages were started to be developed, > and this was very good. And then there were various new programming > paradigms developed, and so on. What I am wondering is, is there a > good book that covers in relatively good detail how we started at the > most primitive level, machine code, and evolved to our current > wonderful cornucopia of languages, operating systems, etc.? As the > different threads reveal bits and pieces of the low level guts of > Python, I am becoming more and more fascinated about how all of this > is managed. Just the brief discussion of garbage collection details > going on I find quite interesting. > > -- > boB you might start here: https://en.wikipedia.org/wiki/History_of_programming_languages -- Joel Goldstick http://joelgoldstick.com From robertvstepp at gmail.com Mon Apr 20 05:34:43 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 19 Apr 2015 22:34:43 -0500 Subject: [Tutor] How to close a Tkinter window from a different thread? Message-ID: I am not certain that my terminology is correct in the subject line. Let me explain my issue. Scenario A: 1) I start out inside a commercial software environment (Abbreviated CSA henceforth). 2) I initiate a script in the CSA's scripting language. 3) This script calls an external Python script.com 4) This Python script generates a Tkinter window, populating it with information from the CSA. 5) Control will not pass back to the CSA until the Tkinter window is closed. Because of this, none of the CSA's tools can be used until the Tkinter window is closed. Scenario B: 1) I start out inside the CSA. 2) I initiate a script in the CSA's scripting language. 3) This script calls an external Python script in a new thread. 4) This Python script generates a Tkinter window, populating it with information from the CSA. 5) Control returns to the CSA while the Tkinter window is populating itself. The CSA's tools can be used while the Tkinter window remains open displaying its information. My users want scenario B to occur. This way they can refer to the Tkinter window's info and make changes to their plan based on this info. However! Once they make their changes they will want to rerun the same Python script. This would then result in TWO Tkinter windows being open, one displaying the old info, the new one with the post-changes info. This is not acceptable. So, how do I: 1) Check for the existence of an already open window from a previous running of the script? 2) If such a window exists, how do I close it from the new script execution? And, then, of course generate a new instance of the information window. I need to be able to identify the existence of such a window without causing anything to happen to the CSA's normally open windows. And then close the particular window I need closed -- IF it is even open. I feel the solution must be in Tkinter's access to the X Window system, but nothing in the documentation is *clicking* with me yet. Thanks! -- boB From alan.gauld at btinternet.com Mon Apr 20 09:10:38 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 08:10:38 +0100 Subject: [Tutor] How to close a Tkinter window from a different thread? In-Reply-To: References: Message-ID: On 20/04/15 04:34, boB Stepp wrote: > So, how do I: > 1) Check for the existence of an already open window from a previous > running of the script? > 2) If such a window exists, how do I close it from the new script > execution? And, then, of course generate a new instance of the > information window. I would suggest forgetting about windows and think about the processes that create them. Use the OS tools (via the os module) to see if the first process is still running. If so kill the process - which will in turn kill the window. You can find the process based on its name or based on its PID which you could store in a file somewhere (like in /tmp?) > I feel the solution must be in Tkinter's access to the X Window > system, but nothing in the documentation is *clicking* with me yet. Trying to manipulate GUIs via the windowing system should always be a last resort, it is very hard to get right. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cybervigilante at gmail.com Mon Apr 20 05:49:27 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sun, 19 Apr 2015 20:49:27 -0700 Subject: [Tutor] sample dictionairies Message-ID: For randomly generating data which look like addresses, I use: > http://www.generatedata.com/ > > While it has 'export to programming language' as a feature, Python isn't > one of the supported languages. Which is fine. It can export into comma > separated values, and writing a Python program to construct a dictionary > from comma separated values is easy. > > Laura > That's a great source, and I can generate dictionaries using the other advice. If you don't request comma delimited, each record per line has | as a field delimiter, so making big dicts was easy. Naturally, I tried emailing one of the addresses - aliquam at Nunc.org - but it appears to be dead ;') Come to think of it, since I used | as a delimiter, what happens if you generate a CSV file from data that already has commas in the text? -- Jim From niyniyniym at gmail.com Mon Apr 20 02:36:59 2015 From: niyniyniym at gmail.com (niy mor) Date: Sun, 19 Apr 2015 20:36:59 -0400 Subject: [Tutor] Life Grid Implementation Message-ID: Is my code completing the assignment??? I need some *guidance* on completing my assignment. My Assignment: A sparse life grid is used to store and represent the area in the game of Life that contains organisms. The grid contains a rectangular grouping of cells divided into an infinite number of rows and columns. The individual cells, which can be alive or dead, are referenced by integer row and column indices. The operations defined for the ADT are as follows: ? SparseLifeGrid() Creates a new infinite-sized game grid with all cells initially dead. ? minRange() Returns a 2-tuple (minrow, mincol) that contains the minimum row index and the minimum column index that is currently occupied by a live cell. The tuple (0, 0) is returned if there are no live cells. ? maxRange() Returns a 2-tuple (maxrow, maxcol) that contains the maximum row index and the maximum column index that is currently occupied by a live cell. The tuple (0, 0) is returned if there are no live cells. ? clearCell(row, col) Clears the individual cell (row, col) and sets it to dead. If the cell is already dead, no action is taken. ? setCell(row, col) Sets the indicated cell (row, col) to be alive. If the cell is already alive, no action is taken. ? isLiveCell(row, col) Returns a Boolean value indicating if the given cell (row, col) contains a live organism. ? numLiveNeighbors(row, col) Returns the number of live neighbors for the given cell (row, col). The neighbors of a cell include all of the cells immediately surrounding it in all directions. My Attempt Code: class SparseLifeGrid : Cell = ["row", "col"] def __init__( self ): self._rowList = [] self._colList = [] self._cellSet = set() def _binarySearch( self, target ) : low = 0 high = len(self._cellSet - 1) while low <= high : mid = (high + low) // 2 if theList[mid] == target : return (True, mid) elif target < theList[mid] : high = mid - 1 else : low = mid + 1 return (False, low) def minRange( self ): return (sorted(self._rowList)[0], sorted(self._rowList)[0]) def maxRange( self ): return (sorted(self._rowList, reverse = True)[0],\ sorted(self._colList, reverse = True)[0]) # Clears the individual cell (row, col) and sets it to dead. If the cell is # already dead, no action is taken def clearCell( self, row, col ): for item in self : if item == Cell(row, col) : self.remove(item) def setCell( self, row, col ): LIVE_CELL = 1 Cell[row, col] = LIVE_CELL def isLiveCell( self, row, col): return Cell(row,col) in self def numLiveNeighbors( self, row, col ): surround = 0 if self.isLiveCell(row + 1, col) : surround += 1 if self.isLiveCell(row - 1, col) : surround += 1 if self.isLiveCell(row, col + 1) : surround += 1 if self.isLiveCell(row, col - 1) : surround += 1 From alan.gauld at btinternet.com Mon Apr 20 09:26:35 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 08:26:35 +0100 Subject: [Tutor] sample dictionairies In-Reply-To: References: Message-ID: On 20/04/15 04:49, Jim Mooney wrote: > Come to think of it, since I used | as a delimiter, what happens if you > generate a CSV file from data that already has commas in the text? The CSV format covers that eventuality: You put quotes around the item with the comma. And if there are already quotes? And if there are newlines inside one of the fields? Its all covered in the CSV spec. Which is why you should use the csv module to work with csv files, it knows how to deal with these various exceptional cases. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From ben+python at benfinney.id.au Mon Apr 20 09:30:39 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Mon, 20 Apr 2015 17:30:39 +1000 Subject: [Tutor] Life Grid Implementation References: Message-ID: <85r3rfntnk.fsf@benfinney.id.au> niy mor writes: > Is my code completing the assignment??? Does it meet the requirements when you (and other people) run the code? > I need some *guidance* on completing my assignment. Can you be specific about what you don't understand? If you don't understand the requirements, that is best discussed with your course supervisor, not us. -- \ ?Kissing a smoker is like licking an ashtray.? ?anonymous | `\ | _o__) | Ben Finney From alan.gauld at btinternet.com Mon Apr 20 09:39:50 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 08:39:50 +0100 Subject: [Tutor] Life Grid Implementation In-Reply-To: References: Message-ID: On 20/04/15 01:36, niy mor wrote: > Is my code completing the assignment??? No. > I need some *guidance* on > completing my assignment. Try running your code. Then fix the errors. If you can't fix them come back to us and ask for help, including the error message and a description of what happened and what you expected. > My Attempt Code: > class SparseLifeGrid : > > Cell = ["row", "col"] What is this for? > def __init__( self ): > self._rowList = [] > self._colList = [] > self._cellSet = set() > > def _binarySearch( self, target ) : > low = 0 > high = len(self._cellSet - 1) > while low <= high : > mid = (high + low) // 2 > if theList[mid] == target : > return (True, mid) > elif target < theList[mid] : > high = mid - 1 > else : > low = mid + 1 > > return (False, low) This just tells you which half the item is in. Is that what you wanted? > def minRange( self ): > return (sorted(self._rowList)[0], sorted(self._rowList)[0]) This returns the same value twice. > def maxRange( self ): > return (sorted(self._rowList, reverse = True)[0],\ > sorted(self._colList, reverse = True)[0]) You don;t need the line continuation character (/) if you are inside parens. def f(): return (expression1, expression2) > # Clears the individual cell (row, col) and sets it to dead. If the > cell is > # already dead, no action is taken > def clearCell( self, row, col ): > for item in self : > if item == Cell(row, col) : > self.remove(item) How do you expect to iterate over self? self is your class instance but it has nothing to iterate over? > def setCell( self, row, col ): > LIVE_CELL = 1 > Cell[row, col] = LIVE_CELL Here you create a new Cell instance then try to assign a value to it, then throw it away. I'm pretty sure thats not what you want. > def isLiveCell( self, row, col): > return Cell(row,col) in self Again how are you testing 'in' self. There is nothing in your class to support that. > > def numLiveNeighbors( self, row, col ): > surround = 0 > if self.isLiveCell(row + 1, col) : > surround += 1 > if self.isLiveCell(row - 1, col) : > surround += 1 > if self.isLiveCell(row, col + 1) : > surround += 1 > if self.isLiveCell(row, col - 1) : > surround += 1 How many neighbours does a cell have in a Life grid? Is it only 4? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From breamoreboy at yahoo.co.uk Mon Apr 20 09:55:21 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Mon, 20 Apr 2015 08:55:21 +0100 Subject: [Tutor] sample dictionairies In-Reply-To: References: Message-ID: On 20/04/2015 04:49, Jim Mooney wrote: > For randomly generating data which look like addresses, I use: > >> http://www.generatedata.com/ >> >> While it has 'export to programming language' as a feature, Python isn't >> one of the supported languages. Which is fine. It can export into comma >> separated values, and writing a Python program to construct a dictionary >> from comma separated values is easy. >> >> Laura >> > > That's a great source, and I can generate dictionaries using the other > advice. If you don't request comma delimited, each record per line has | > as a field delimiter, so making big dicts was easy. Naturally, I tried > emailing one of the addresses - aliquam at Nunc.org - but it appears to be > dead ;') > > Come to think of it, since I used | as a delimiter, what happens if you > generate a CSV file from data that already has commas in the text? > For those who don't know you can use any character as the delimiter and any character as the quote, see https://docs.python.org/3/library/csv.html#csv.reader -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From robertvstepp at gmail.com Mon Apr 20 14:45:50 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Mon, 20 Apr 2015 07:45:50 -0500 Subject: [Tutor] How to close a Tkinter window from a different thread? In-Reply-To: References: Message-ID: On Mon, Apr 20, 2015 at 2:10 AM, Alan Gauld wrote: > On 20/04/15 04:34, boB Stepp wrote: > >> So, how do I: >> 1) Check for the existence of an already open window from a previous >> running of the script? >> 2) If such a window exists, how do I close it from the new script >> execution? And, then, of course generate a new instance of the >> information window. > > > I would suggest forgetting about windows and think about > the processes that create them. Use the OS tools (via > the os module) to see if the first process is still running. > If so kill the process - which will in turn kill the window. I started poking around a little in this area in my books, but did not know if this was the way to go or not. I was still hung up on how to identify the correct process... > You can find the process based on its name or based on > its PID which you could store in a file somewhere > (like in /tmp?) I was thinking in these terms from a Tkinter window id perspective, but storing the PID while the original window is known to be open looks like the way to go. Thanks, Alan! I may have more questions on this later as I have not explicitly worked with this via Python. I've only killed processes via the command line before. >> I feel the solution must be in Tkinter's access to the X Window >> system, but nothing in the documentation is *clicking* with me yet. > > > Trying to manipulate GUIs via the windowing system should always > be a last resort, it is very hard to get right. If I am learning nothing else from my exploration of GUI programming, this is becoming ever more evident! -- boB From cybervigilante at gmail.com Mon Apr 20 09:44:12 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Mon, 20 Apr 2015 00:44:12 -0700 Subject: [Tutor] bin to dec conversion puzzlement Message-ID: I can't seem to get my head around this 'simple' book example of binary-to-decimal conversion, which goes from left to right: B = '11011101' I = 0 while B: I = I * 2 + int(B[0]) B = B[1:] print(I) >>> 221 My thought was to go from right to left, multiplying digits by successive powers of two, and adding, like so: B = '11011101' sum = 0 for exp, num in enumerate(reversed(B)): sum += int(num) * 2**exp print(sum) >> 221 Both methods work but I just can't see how the first one does. Am I missing something obvious here? -- Jim From cybervigilante at gmail.com Mon Apr 20 09:50:33 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Mon, 20 Apr 2015 00:50:33 -0700 Subject: [Tutor] sample dictionairies In-Reply-To: References: Message-ID: > Which is why you should use the csv module to work with csv files, > it knows how to deal with these various exceptional cases. > -- > Alan G > I should have known to simply try importing csv. Must-remember-batteries-included ;') -- Jim From lac at openend.se Mon Apr 20 10:49:41 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 20 Apr 2015 10:49:41 +0200 Subject: [Tutor] OT: Is there a good book that covers the history/evolution of software? [Inspired by the thread: lists, name semantics] In-Reply-To: Message from boB Stepp of "Sun, 19 Apr 2015 20:03:02 -0500." References: Message-ID: <201504200849.t3K8ngkK008889@fido.openend.se> Newman, W., Sproull, R. (1979), Principles of Interactive Computer Graphics, Mcgraw-Hill College, ISBN 0-07-046338-7 is a very good read. It is understandably dated, but then it was history that you were looking for. And the book has 2 parts -- a history of the computer architectures we had (in 1979) and then the part on how to make grapical programs on them. Laura From lac at openend.se Mon Apr 20 11:40:33 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 20 Apr 2015 11:40:33 +0200 Subject: [Tutor] How to close a Tkinter window from a different thread? In-Reply-To: Message from Alan Gauld of "Mon, 20 Apr 2015 08:10:38 +0100." References: Message-ID: <201504200940.t3K9eXLM010578@fido.openend.se> In a message of Mon, 20 Apr 2015 08:10:38 +0100, Alan Gauld writes: >Trying to manipulate GUIs via the windowing system should always >be a last resort, it is very hard to get right. And the hardness increases exponentially if you want to be portable across different operating systems. Laura From lac at openend.se Mon Apr 20 11:45:16 2015 From: lac at openend.se (Laura Creighton) Date: Mon, 20 Apr 2015 11:45:16 +0200 Subject: [Tutor] sample dictionairies In-Reply-To: Message from Jim Mooney of "Sun, 19 Apr 2015 20:49:27 -0700." References: Message-ID: <201504200945.t3K9jG4p010702@fido.openend.se> In a message of Sun, 19 Apr 2015 20:49:27 -0700, Jim Mooney writes: >Come to think of it, since I used | as a delimiter, what happens if you >generate a CSV file from data that already has commas in the text? > >-- >Jim In Sweden, and lots of other places, we do numbers differently. This is One thousand dollars and 43 cents. 1.000,43 Lots of the time you write that as 1000,43 same as in English you get 1000.43 and 1,000.43. So we tend to use comma separated values around here that are really semi-colon separated values. But I do not know how widespread that usage is. Laura From mchirmure at gmail.com Mon Apr 20 10:54:46 2015 From: mchirmure at gmail.com (Mahesh Chiramure) Date: Mon, 20 Apr 2015 14:24:46 +0530 Subject: [Tutor] Please Help to build an addon for Anki In-Reply-To: References: Message-ID: Hi I liked the addon "Picture-flasher" written for anki very much and I was wondering if the same thing could be done with mp3 and/or flac files. Means I am looking for an addon that chooses a random mp3 and/or flac file from a directory provided by me (to the addon as we have to provide in "Picture-flasher") and plays it on successful reviewing of a certain number of cards (as does the addon "Picture-flasher"). As a music lover, I feel that this addon can motivate a whole lot of music lovers out there to pay a visit to Anki on their PC and review to listen to their favorite mp3 and/or flac files as a reward. I am not a programmer yet, please guide. Hoping for a quick response. Mahesh Chirmure -------------- next part -------------- # -*- coding: utf-8 -*- # Picture-Flasher (a plugin for Anki) # Authors: # Emanuel Rylke, ema-fox at web.de # D_Malik, malik6174 at gmail.com # Version 2 # License: GNU GPL, version 3 or later; http://www.gnu.org/copyleft/gpl.html """ A simple plugin that flashes pictures on-screen to reinforce reviews. Before using: - Get pictures from someplace. I downloaded pictures off reddit using the script at https://github.com/dpbrown/RedditImageGrab - Change all lines (in the plugin source) marked with "CHANGEME" according to your preferences. For more details, see the post at For more details, see the post at http://lesswrong.com/r/discussion/lw/frc/two_anki_plugins_to_reinforce_reviewing/ """ from anki.hooks import addHook from aqt import mw from random import random, choice from aqt.qt import QSplashScreen, QPixmap, QTimer from os import listdir #------ begin configuration ------# pictureDirectory = "E://Family stuff//22 Feb//Personal//College//A J//" #CHANGEME to the directory where you're storing your pictures. NB: This MUST end with a trailing slash e.g. D://Family stuff//19 Jan//Imgs//Wallys//, D://Family stuff//22 Feb//Imgs//Windows 7//. flashTime = 3000 #CHANGEME to change how long pictures stay on the screen. The number is time in milliseconds. #flashPosition = [20, 1050] #CHANGEME if you want the picture to be shown at a specific location. The numbers are x- and y-coordinates. #CHANGEME: The next lines are a python dictionary associating deck names with probabilities of pictures being shown. #Eg, when using the deck "brainscience", you will get a picture after 30% of cards. When using a deck without a listed name, "other" is used. #Change this according to your decks. Decks with shorter, easier cards need lower probabilities. deckPicsProbabilities = { "rocketsurgery" : 0.3, "brainscience" : 0.5, "other" : 0.1, } #------- end configuration -------# pics = listdir(pictureDirectory) def showPics(): if mw.col.decks.current()['name'] in deckPicsProbabilities: picsProbability = deckPicsProbabilities[mw.col.decks.current()['name']] else: picsProbability = deckPicsProbabilities["other"] if random() < picsProbability: mw.splash = QSplashScreen(QPixmap(pictureDirectory + choice(pics))) try: mw.splash.move(flashPosition[0], flashPosition[1]) except NameError: pass mw.splash.show() QTimer.singleShot(flashTime, mw.splash.close) addHook("showQuestion", showPics) From niyanaxx95 at gmail.com Mon Apr 20 14:59:20 2015 From: niyanaxx95 at gmail.com (niyana morgan) Date: Mon, 20 Apr 2015 08:59:20 -0400 Subject: [Tutor] Life Grid Implementation In-Reply-To: <85r3rfntnk.fsf@benfinney.id.au> References: <85r3rfntnk.fsf@benfinney.id.au> Message-ID: I don't understand how to do this. I attempted with my code and hoped a tutor could help me with this On Apr 20, 2015 3:31 AM, "Ben Finney" wrote: > niy mor writes: > > > Is my code completing the assignment??? > > Does it meet the requirements when you (and other people) run the code? > > > I need some *guidance* on completing my assignment. > > Can you be specific about what you don't understand? > > If you don't understand the requirements, that is best discussed with > your course supervisor, not us. > > -- > \ ?Kissing a smoker is like licking an ashtray.? ?anonymous | > `\ | > _o__) | > Ben Finney > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From marc.tompkins at gmail.com Mon Apr 20 17:21:11 2015 From: marc.tompkins at gmail.com (Marc Tompkins) Date: Mon, 20 Apr 2015 08:21:11 -0700 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: On Apr 20, 2015 6:56 AM, "Jim Mooney" wrote: > > I can't seem to get my head around this 'simple' book example of > binary-to-decimal conversion, which goes from left to right: > > B = '11011101' > I = 0 > while B: > I = I * 2 + int(B[0]) > B = B[1:] > > print(I) > >>> 221 > > My thought was to go from right to left, multiplying digits by successive > powers of two, and adding, like so: > > B = '11011101' > sum = 0 > > for exp, num in enumerate(reversed(B)): > sum += int(num) * 2**exp > > print(sum) > >> 221 > > Both methods work but I just can't see how the first one does. Am I missing > something obvious Start from 0. As long as there are any digits left, a) Multiply by 2, add the leftmost digit. b) Chop off the leftmost digit. Lather, rinse, repeat. It _does_ seem counterintuitive to do it from the left, but it's actually quite simple. From oscar.j.benjamin at gmail.com Mon Apr 20 17:24:57 2015 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Mon, 20 Apr 2015 16:24:57 +0100 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: On 20 April 2015 at 08:44, Jim Mooney wrote: > I can't seem to get my head around this 'simple' book example of > binary-to-decimal conversion, which goes from left to right: > > B = '11011101' > I = 0 > while B: > I = I * 2 + int(B[0]) > B = B[1:] Follow through the loop and see what happens. To begin I is zero and B is the full string. Consider B_orig to be the original string. After the first iteration we have that I = B[0] and B = B_orig[1:] then I = 2*B[0] + B[1] and B = B_orig[2:] then I = 2*(2*B[0] + B[1]) + B[2] = 4*B[0] + 2*B[1] + B[2] then I = 8*B[0] + 4*B[1] + 2*B[2] + B[3] and eventually I = 128*B[0] + 64*B[1] + ... + 2*B[6] + B[7] which is the desired result. Oscar From akleider at sonic.net Mon Apr 20 17:24:42 2015 From: akleider at sonic.net (Alex Kleider) Date: Mon, 20 Apr 2015 08:24:42 -0700 Subject: [Tutor] introspection Message-ID: Does python provide the introspective ability to retrieve the name to which an object is bound? For example: $ python3 Python 3.4.0 (default, Apr 11 2014, 13:05:18) [GCC 4.8.2] on linux Type "help", "copyright", "credits" or "license" for more information. >>> a = 69 >>> print("Identifier <{}> is bound to {}.".format(a.__name__, a)) Traceback (most recent call last): File "", line 1, in AttributeError: 'int' object has no attribute '__name__' From joel.goldstick at gmail.com Mon Apr 20 18:15:44 2015 From: joel.goldstick at gmail.com (Joel Goldstick) Date: Mon, 20 Apr 2015 12:15:44 -0400 Subject: [Tutor] introspection In-Reply-To: References: Message-ID: On Mon, Apr 20, 2015 at 11:24 AM, Alex Kleider wrote: > Does python provide the introspective ability to retrieve the name to which > an object is bound? > > For example: > $ python3 > Python 3.4.0 (default, Apr 11 2014, 13:05:18) > [GCC 4.8.2] on linux > Type "help", "copyright", "credits" or "license" for more information. >>>> >>>> a = 69 >>>> print("Identifier <{}> is bound to {}.".format(a.__name__, a)) > > Traceback (most recent call last): > File "", line 1, in > AttributeError: 'int' object has no attribute '__name__' > > An object can be bound to multiple names. Within a namespace you can use locals to see names, then compare various names like so: > >>> a = 3 >>> b = 6 >>> c = a >>> locals() {'a': 3, 'c': 3, 'b': 6, '__builtins__': , '__package__': None, '__name__': '__main__', '__doc__': None} >>> a is b False >>> a is c True >>> > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor -- Joel Goldstick http://joelgoldstick.com From alan.gauld at btinternet.com Mon Apr 20 18:16:27 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 17:16:27 +0100 Subject: [Tutor] Life Grid Implementation In-Reply-To: References: <85r3rfntnk.fsf@benfinney.id.au> Message-ID: On 20/04/15 13:59, niyana morgan wrote: > I don't understand how to do this. I attempted with my code and hoped a > tutor could help me with this Always write code that runs. Then fix the mistakes as they happen. That way you only have a few lines of code to look at. Your code is far too big and intertwined to be able to debug easily. Look at your specification: ? SparseLifeGrid() Creates a new infinite-sized game grid with all cells initially dead. ... ? clearCell(row, col) Clears the individual cell (row, col) and sets it to dead. If the cell is already dead, no action is taken. ? setCell(row, col) Sets the indicated cell (row, col) to be alive. If the cell is already alive, no action is taken. .... I suggest you start over with a class definition and an init(). See if you can create an instance and if it has the fields you expect. Thats your first API bullet done. Once you can do that create the methods needed to populate it with data (setCell()) and clear a cell(clearCell()). Nothing else, just those two methods. Get them working. Now you have three parts of your assignment done. Only when you can do those things correctly attempt one of the remaining API methods - maybe the isLiveCell() method. Then try minRange and maxRange after that. Finally you can try numLiveNeighbours confident that the rest of the class works. Always run the code. Every time you complete a method your code should work. If you write your tests as code in a function, that function should always work even after you complete a new stage. If anything that used to work stops working, go back and fix it before trying anything new. The code you changed will still be fresh in your mind. If you really get stuck come back here and ask. Always copy any error messages in full. HTH -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Mon Apr 20 18:21:51 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 17:21:51 +0100 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: On 20/04/15 08:44, Jim Mooney wrote: > I can't seem to get my head around this 'simple' book example of > binary-to-decimal conversion, which goes from left to right: > > B = '11011101' > I = 0 > while B: > I = I * 2 + int(B[0]) > B = B[1:] ... > Both methods work but I just can't see how the first one does. The key is that the result gets multiplied by 2 each time so for an N bit number the leftmost digit winds up being effectively 2**N, which is what you want. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Mon Apr 20 18:27:25 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 17:27:25 +0100 Subject: [Tutor] Please Help to build an addon for Anki In-Reply-To: References: Message-ID: On 20/04/15 09:54, Mahesh Chiramure wrote: > I liked the addon "Picture-flasher" written for anki very much > and I was wondering if the same thing could be done with mp3 and/or > flac files. Probably, but I (and probably most of the list) have no idea what anki is or what the addon does. This is a list for learning Python and its standard library. You could try asking on the general Python mailinglist/newsgroup where you might find someone familiar with it. If you do try that you sould try explaining what anki is, and what the addon does. ie how it 'adds on'. Better still is if you can find an anki forum, since they will understand anki, addons and probably be familiar with the PictureFlasher one you describe. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From akleider at sonic.net Mon Apr 20 18:55:41 2015 From: akleider at sonic.net (Alex Kleider) Date: Mon, 20 Apr 2015 09:55:41 -0700 Subject: [Tutor] introspection In-Reply-To: References: Message-ID: <53b5d70a1b929de9cad143f11802c795@sonic.net> On 2015-04-20 09:15, Joel Goldstick wrote: > On Mon, Apr 20, 2015 at 11:24 AM, Alex Kleider > wrote: >> Does python provide the introspective ability to retrieve the name to >> which >> an object is bound? >> >> For example: >> $ python3 >> Python 3.4.0 (default, Apr 11 2014, 13:05:18) >> [GCC 4.8.2] on linux >> Type "help", "copyright", "credits" or "license" for more information. >>>>> >>>>> a = 69 >>>>> print("Identifier <{}> is bound to {}.".format(a.__name__, a)) >> >> Traceback (most recent call last): >> File "", line 1, in >> AttributeError: 'int' object has no attribute '__name__' >> >> > An object can be bound to multiple names. Within a namespace you can > use locals to see names, then compare various names like so: >> >>>> a = 3 >>>> b = 6 >>>> c = a >>>> locals() > {'a': 3, 'c': 3, 'b': 6, '__builtins__': (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': > None} >>>> a is b > False >>>> a is c > True Showing my desired use case might make my question more understandable: def debug(var_name): if args["--debug"]: print("Identifier <{}> is bound to: {}" .format(var_name.__name__, repr(var_name))) I don't think the built in locals() can help me. Thanks all the same. Alex From akleider at sonic.net Mon Apr 20 18:58:37 2015 From: akleider at sonic.net (Alex Kleider) Date: Mon, 20 Apr 2015 09:58:37 -0700 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: On 2015-04-20 09:21, Alan Gauld wrote: > On 20/04/15 08:44, Jim Mooney wrote: >> I can't seem to get my head around this 'simple' book example of >> binary-to-decimal conversion, which goes from left to right: >> >> B = '11011101' >> I = 0 >> while B: >> I = I * 2 + int(B[0]) >> B = B[1:] > ... >> Both methods work but I just can't see how the first one does. > > The key is that the result gets multiplied by 2 each time > so for an N bit number the leftmost digit winds up being > effectively 2**N, which is what you want. Shouldn't that be 2**(N-1)? From alan.gauld at btinternet.com Mon Apr 20 19:14:33 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 18:14:33 +0100 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: On 20/04/15 17:58, Alex Kleider wrote: >> The key is that the result gets multiplied by 2 each time >> so for an N bit number the leftmost digit winds up being >> effectively 2**N, which is what you want. > > Shouldn't that be 2**(N-1)? Yes, sorry. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From eryksun at gmail.com Mon Apr 20 19:14:27 2015 From: eryksun at gmail.com (eryksun) Date: Mon, 20 Apr 2015 12:14:27 -0500 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: On Mon, Apr 20, 2015 at 11:21 AM, Alan Gauld wrote: >> >> B = '11011101' >> I = 0 >> while B: >> I = I * 2 + int(B[0]) >> B = B[1:] > >> Both methods work but I just can't see how the first one does. > > The key is that the result gets multiplied by 2 each time > so for an N bit number the leftmost digit winds up being > effectively 2**N, which is what you want. The loop iterates N times, so the leftmost digit is multiplied by 2 a total of N - 1 times, i.e. B[0] * 2 ** (N - 1). Another way to see this is that multiplying by 2 is a bitwise left shift. Thus you can replace the multiplication and addition with bitwise operations as follows: B = '11011101' I = 0 while B: I = (I << 1) | int(B[0], 2) B = B[1:] assert I == 221 Shifting the values in like this may be more intuitively obvious. From steve at pearwood.info Mon Apr 20 19:15:17 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 21 Apr 2015 03:15:17 +1000 Subject: [Tutor] introspection In-Reply-To: References: Message-ID: <20150420171516.GG5663@ando.pearwood.info> On Mon, Apr 20, 2015 at 08:24:42AM -0700, Alex Kleider wrote: > Does python provide the introspective ability to retrieve the name to > which an object is bound? Short answer: no. Slightly longer answer: it *may* be possible if you dig deep into the debugger API that you might find something which does what you want. I'm not saying that it will, only that if it exists, the debugger seems like the most likely place. But... probably not. In any case, even if you find something that will do this, it will be implementation-specific (e.g. Jython only, or IronPython only, or CPython only, but not all three) and probably rather dubious. After all, any object may have zero, one or more names, in completely different scopes. The whole idea of "what name does this object have" is rather dubious. The best one can do is say "in this namespace (locals), does this object have any names?". -- Steve From alan.gauld at btinternet.com Mon Apr 20 19:33:33 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 20 Apr 2015 18:33:33 +0100 Subject: [Tutor] introspection In-Reply-To: <53b5d70a1b929de9cad143f11802c795@sonic.net> References: <53b5d70a1b929de9cad143f11802c795@sonic.net> Message-ID: On 20/04/15 17:55, Alex Kleider wrote: >>>>> locals() >> {'a': 3, 'c': 3, 'b': 6, '__builtins__': > (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': >> None} > Showing my desired use case might make my question more understandable: > def debug(var_name): > if args["--debug"]: > print("Identifier <{}> is bound to: {}" > .format(var_name.__name__, repr(var_name))) > I don't think the built in locals() can help me. Why not? Provided you pass the required scope into your function: def debug(var_name, scope): if args["--debug"]: print("Identifier <{}> is bound to: {}" .format(var_name, scope.get(var_name, 'no object')) debug('a',locals()) # look in local vars -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Mon Apr 20 19:34:27 2015 From: __peter__ at web.de (Peter Otten) Date: Mon, 20 Apr 2015 19:34:27 +0200 Subject: [Tutor] introspection References: <53b5d70a1b929de9cad143f11802c795@sonic.net> Message-ID: Alex Kleider wrote: > On 2015-04-20 09:15, Joel Goldstick wrote: >> On Mon, Apr 20, 2015 at 11:24 AM, Alex Kleider >> wrote: >>> Does python provide the introspective ability to retrieve the name to >>> which >>> an object is bound? >>> >>> For example: >>> $ python3 >>> Python 3.4.0 (default, Apr 11 2014, 13:05:18) >>> [GCC 4.8.2] on linux >>> Type "help", "copyright", "credits" or "license" for more information. >>>>>> >>>>>> a = 69 >>>>>> print("Identifier <{}> is bound to {}.".format(a.__name__, a)) >>> >>> Traceback (most recent call last): >>> File "", line 1, in >>> AttributeError: 'int' object has no attribute '__name__' >>> >>> >> An object can be bound to multiple names. Within a namespace you can >> use locals to see names, then compare various names like so: >>> >>>>> a = 3 >>>>> b = 6 >>>>> c = a >>>>> locals() >> {'a': 3, 'c': 3, 'b': 6, '__builtins__': > (built-in)>, '__package__': None, '__name__': '__main__', '__doc__': >> None} >>>>> a is b >> False >>>>> a is c >> True > > Showing my desired use case might make my question more understandable: > def debug(var_name): > if args["--debug"]: > print("Identifier <{}> is bound to: {}" > .format(var_name.__name__, repr(var_name))) > I don't think the built in locals() can help me. > Thanks all the same. > Alex In CPython you can inspect the callstack, but remember that (1) it is a costly operation (2) there are many variables bound to multiple names or none at all. $ cat show_name_binding2.py import sys def bindings_of(value, depth): frame = sys._getframe(depth + 1) bindings = [n for n, v in frame.f_locals.items() if v is value] if bindings: return bindings return [""] def debug(value): print("{} is bound to {}".format( value, ", ".join(bindings_of(value, 1)))) def main(): x = 42 y = 42 debug(42) debug("foo") a = "bar baz" b = " ".join(a.split()) assert a == b debug("bar baz") if __name__ == "__main__": main() $ python3 show_name_binding2.py 42 is bound to y, x foo is bound to bar baz is bound to a From fomcl at yahoo.com Mon Apr 20 22:05:12 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Mon, 20 Apr 2015 20:05:12 +0000 (UTC) Subject: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2? Message-ID: <1793882820.317947.1429560312853.JavaMail.yahoo@mail.yahoo.com> Hi, My Raspberry Pi 2 comes with Python 3.2 (and 2.7). I run some code that uses the datetime module but I get an error: "AttributeError: 'datetime.datetime' object has no attribute 'timestamp'". On https://docs.python.org/3/whatsnew/3.3.html I see: "New datetime.datetime.timestamp() method: Return POSIX timestamp corresponding to thedatetime instance." Is upgrading Python 3.3 or higher my only option, or is it somehow possible to use the newer version of the datetime library for Python 3.2? I do not want to modify the source code of the library that causes the error (pysolar). Thanks! Regards, Albert-Jan ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From ben+python at benfinney.id.au Mon Apr 20 22:18:39 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Tue, 21 Apr 2015 06:18:39 +1000 Subject: [Tutor] sample dictionairies References: Message-ID: <85iocqo8o0.fsf@benfinney.id.au> Jim Mooney writes: > I should have known to simply try importing csv. Better: You should now know to refer to the documentation . -- \ ?Speech is conveniently located midway between thought and | `\ action, where it often substitutes for both.? ?John Andrew | _o__) Holmes, _Wisdom in Small Doses_ | Ben Finney From ben+python at benfinney.id.au Mon Apr 20 22:24:22 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Tue, 21 Apr 2015 06:24:22 +1000 Subject: [Tutor] introspection References: Message-ID: <85egneo8eh.fsf@benfinney.id.au> Alex Kleider writes: > Does python provide the introspective ability to retrieve the name to > which an object is bound? Objects aren't bound to names. So, no. The binding from a reference (a name is a reference) to objects is one-way. See this excellent presentation from PyCon US 2015 by Ned Batchelder . -- \ ?I must say that I find television very educational. The minute | `\ somebody turns it on, I go to the library and read a book.? | _o__) ?Groucho Marx | Ben Finney From ben+python at benfinney.id.au Mon Apr 20 22:47:17 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Tue, 21 Apr 2015 06:47:17 +1000 Subject: [Tutor] bin to dec conversion puzzlement References: Message-ID: <854moao7ca.fsf@benfinney.id.au> Jim Mooney writes: > I can't seem to get my head around this 'simple' book example of > binary-to-decimal conversion, which goes from left to right: > > B = '11011101' > I = 0 > while B: > I = I * 2 + int(B[0]) > B = B[1:] > > print(I) > >>> 221 That is, IMO, a needlessly confusing way to write that code. Whoever wrote it is clearly pleased with how clever it is; but cleverness is almost always a property of *bad* code because it's difficult to understand at a glance. That's the case here. One significant problem with the code as written is that it uses a ?while? loop and mutates the list, where there's no point; it should just iterate over items *from* the list without changing it. Another significant problem is that it uses moronically-short, completely unexpressive names. This is Python not FORTRAN. Try this:: binary_text = '11011101' result = 0 for binary_digit in binary_text: # Accumulate powers of 2 for each digit. result = result * 2 + int(binary_digit) print(result) > Both methods work but I just can't see how the first one does. Am I > missing something obvious here? No, you were missing something needlessly obscured by the badly-written code. Which book is this? I will be sure never to recommend it. Hope that helps. -- \ ?Science is a way of trying not to fool yourself. The first | `\ principle is that you must not fool yourself, and you are the | _o__) easiest person to fool.? ?Richard P. Feynman, 1964 | Ben Finney From cybervigilante at gmail.com Mon Apr 20 22:15:09 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Mon, 20 Apr 2015 13:15:09 -0700 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: The key is that the result gets multiplied by 2 each time > so for an N bit number the leftmost digit winds up being > effectively 2**N, which is what you want. > > Alan G Ah, the light dawns once it was restated. It would be even simpler if you could multiply each element of the binary number by it's respective power of two, and sum them all at once. I hear Py 3.5 will have vector abilities. I wonder it if would do something like that. Jim From davea at davea.name Tue Apr 21 01:43:51 2015 From: davea at davea.name (Dave Angel) Date: Mon, 20 Apr 2015 19:43:51 -0400 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: References: Message-ID: <55358F37.6030508@davea.name> On 04/20/2015 04:15 PM, Jim Mooney wrote: > The key is that the result gets multiplied by 2 each time > >> so for an N bit number the leftmost digit winds up being >> effectively 2**N, which is what you want. >> > > >> Alan G > > > Ah, the light dawns once it was restated. It would be even simpler if you > could multiply each element of the binary number by it's respective power > of two, and sum them all at once. I hear Py 3.5 will have vector abilities. > I wonder it if would do something like that. It's important to understand these conversion methods, or I would have earlier mentioned that you can convert from a binary string simply by x = int("1011", 2) No loop needed. But if you need a loop for an analagous algorithm, find a way to either minimize the number of times through the loop, or to reduce the work done in each loop. Ben's algorithm is much simpler than the one in the book you're reading. binary_text = '11011101' result = 0 for binary_digit in binary_text: # Accumulate powers of 2 for each digit. result = result * 2 + int(binary_digit) print(result) But more importantly, it's much simpler than calculating various powers of two and multiplying the various coefficients by them, and somehow "sum them all at once". -- DaveA From robertvstepp at gmail.com Tue Apr 21 04:34:39 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Mon, 20 Apr 2015 21:34:39 -0500 Subject: [Tutor] How to close a Tkinter window from a different thread? In-Reply-To: References: Message-ID: On Mon, Apr 20, 2015 at 2:10 AM, Alan Gauld wrote: > On 20/04/15 04:34, boB Stepp wrote: > >> So, how do I: >> 1) Check for the existence of an already open window from a previous >> running of the script? >> 2) If such a window exists, how do I close it from the new script >> execution? And, then, of course generate a new instance of the >> information window. > > > I would suggest forgetting about windows and think about > the processes that create them. Use the OS tools (via > the os module) to see if the first process is still running. > If so kill the process - which will in turn kill the window. > > You can find the process based on its name or based on > its PID which you could store in a file somewhere > (like in /tmp?) I'm currently at home and cannot access Solaris, but I believe that the following will do what I want: import os import signal from tkinter import * def kill(): os.kill(pid, signal.SIGKILL) root = Tk() pid = os.getpid() btn = Button(root, text='Kill me!!!', command=kill) btn.pack() root.mainloop() The process id would have to be stored persistently to do the real deal, of course, as Alan suggested. I cannot make this example work in Windows. As far as I can tell, signal.SIGKILL won't work with Windows. If I replace it with 9, then it does work. If I have understood what I have read to date, using signal.SIGKILL is preferable to using 9. Some questions: 1) Is the placement of "pid = os.getpid()" critical? My thinking is that I want to capture the pid of the root window, store it, and then use it if I need to kill the root and any children it has in my actual GUI display. If, say, I placed it immediately before "root.mainloop()", would it do what I want? Of course, I plan to experiment with this at work tomorrow. I'll also continue to play around with it in Windows. 2) The other possibility was to use "os.getppid" and, I suppose, "os.kill(ppid, signal.SIGKILL)". Would this be preferable? Or will wreak some sort of havoc? Thanks! boB From akleider at sonic.net Tue Apr 21 05:46:54 2015 From: akleider at sonic.net (Alex Kleider) Date: Mon, 20 Apr 2015 20:46:54 -0700 Subject: [Tutor] introspection In-Reply-To: <85egneo8eh.fsf@benfinney.id.au> References: <85egneo8eh.fsf@benfinney.id.au> Message-ID: <5b61b455af3848c28968f0b83f176482@sonic.net> On 2015-04-20 13:24, Ben Finney wrote: > Alex Kleider writes: > >> Does python provide the introspective ability to retrieve the name to >> which an object is bound? > > Objects aren't bound to names. So, no. > > The binding from a reference (a name is a reference) to objects is > one-way. > > See this excellent presentation from PyCon US 2015 by Ned Batchelder > . But my code knows the name. The code is provided the name; I want the code to tell me that name. ..but it seems unable to do so. ;-( From dyoo at hashcollision.org Tue Apr 21 07:21:44 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Mon, 20 Apr 2015 22:21:44 -0700 Subject: [Tutor] introspection In-Reply-To: <5b61b455af3848c28968f0b83f176482@sonic.net> References: <85egneo8eh.fsf@benfinney.id.au> <5b61b455af3848c28968f0b83f176482@sonic.net> Message-ID: What's supposed to happen in this situation? ########################################## class Person(object): def __init__(self): pass j = Person() john = j jack = j ########################################## What single name should we get back from the single Person object here? "j", "john", or "jack"? From cybervigilante at gmail.com Tue Apr 21 02:44:58 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Mon, 20 Apr 2015 17:44:58 -0700 Subject: [Tutor] enhanced subtration in an exponent Message-ID: Why does the compiler choke on this? It seems to me that the enhanced subtraction resolves to a legitimate integer in the exponent, but I get a syntax error: B = '11011101' sum = 0 start = len(B) for char in B: sum += int(char) * 2**(start -= 1) ## syntax error print(sum) -- Jim From cybervigilante at gmail.com Tue Apr 21 06:19:34 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Mon, 20 Apr 2015 21:19:34 -0700 Subject: [Tutor] calling a method directly Message-ID: Is there any difference between these two since they give the same result, and when is the second preferred? >>> x = 'ABE' >>> x.lower() 'abe' >>> str.lower(x) 'abe' -- Jim From yanglei.fage at gmail.com Tue Apr 21 07:22:08 2015 From: yanglei.fage at gmail.com (lei yang) Date: Tue, 21 Apr 2015 13:22:08 +0800 Subject: [Tutor] what's wrong with this ? Message-ID: >>>start_time = "2014-7-1" >>> revlines = commands.getoutput("git log --pretty=format:'%ad:%an' --date=short --since='%s' --no-merges" %start_time).strip().split('\n') Traceback (most recent call last): File "", line 1, in ValueError: unsupported format character 'a' (0x61) at index 26 >>> if I directly use revlines = commands.getoutput("git log --pretty=format:'%ad:%an' --date=short --since='2014-7-1' --no-merges" ).strip().split('\n') it works well From danny.yoo at gmail.com Tue Apr 21 09:41:15 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Tue, 21 Apr 2015 00:41:15 -0700 Subject: [Tutor] enhanced subtration in an exponent In-Reply-To: References: Message-ID: On Apr 21, 2015 12:24 AM, "Jim Mooney" wrote: > > Why does the compiler choke on this? It seems to me that the enhanced > subtraction resolves to a legitimate integer in the exponent, but I get a > syntax error: > > B = '11011101' > sum = 0 > start = len(B) > for char in B: > sum += int(char) * 2**(start -= 1) ## syntax error Assignment is a statement. In Python, statements can't be composed. In the last line, it looks like you're trying to do two assignments, in incrementing 'sum' and decrementing 'start'. Try separating that into two separate statements. From danny.yoo at gmail.com Tue Apr 21 09:50:14 2015 From: danny.yoo at gmail.com (Danny Yoo) Date: Tue, 21 Apr 2015 00:50:14 -0700 Subject: [Tutor] what's wrong with this ? In-Reply-To: References: Message-ID: On Apr 21, 2015 12:27 AM, "lei yang" wrote: > > >>>start_time = "2014-7-1" > >>> revlines = commands.getoutput("git log --pretty=format:'%ad:%an' > --date=short --since='%s' --no-merges" %start_time).strip().split('\n') > Traceback (most recent call last): > File "", line 1, in > ValueError: unsupported format character 'a' (0x61) at index 26 Your format string has an embedded format string in it. Although you may think it obvious that Python should know not to touch the embedded format string since there are single quotes, Python doesn't take those single quote characters with any reverence. Therefore, it can't tell that you want to keep the embedded one as a literal. Fundamentally, building a command string with string formatting is error prone: consider the subprocess module and passing an explicit list of arguments, rather than a single string. From alan.gauld at btinternet.com Tue Apr 21 10:03:58 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 21 Apr 2015 09:03:58 +0100 Subject: [Tutor] calling a method directly In-Reply-To: References: Message-ID: On 21/04/15 05:19, Jim Mooney wrote: > Is there any difference between these two since they give the same result, > and when is the second preferred? > >>>> x = 'ABE' >>>> x.lower() > 'abe' >>>> str.lower(x) > 'abe' > They are essentially the same method being accessed in two different ways. The first via the instance, the second via the class. It's a bit like when you call a superclass method in OOP: >>> class C: ... def f(s): print 'in C' ... >>> class D(C): ... def f(s): ... C.f(s) ... print 'and D' ... def g(s): print 'only D' ... In the first line of D.f() you invoke C's foo method by referring to C and passing the local self as the object. You can do it in top level code too: >>> d = D() >>> d.f() in C and D >>> C.f(d) in C >>> >>> d.g() only D >>> D.g(d) only D There are very few cases where the class version is preferred, you nearly always use the instance technique. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Tue Apr 21 10:08:25 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 21 Apr 2015 09:08:25 +0100 Subject: [Tutor] what's wrong with this ? In-Reply-To: References: Message-ID: On 21/04/15 06:22, lei yang wrote: >>>> start_time = "2014-7-1" >>>> revlines = commands.getoutput("git log --pretty=format:'%ad:%an' > --date=short --since='%s' --no-merges" %start_time).strip().split('\n') > Traceback (most recent call last): > File "", line 1, in > ValueError: unsupported format character 'a' (0x61) at index 26 >>>> Your pretty=format argument has a %a in it. Python tries to match percent signs to the values provided but it doesn't know how to process %a. You need to get a literal % sign into your string so you need to double it up. Here is a simpler example: >>> "foo %%5 and %d" % 45 'foo %5 and 45' >>> Alternatively use the more modern subprocess module while helps prevent these kinds of issues by taking all arguments as separate strings in a list. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Tue Apr 21 10:14:29 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 21 Apr 2015 09:14:29 +0100 Subject: [Tutor] enhanced subtration in an exponent In-Reply-To: References: Message-ID: On 21/04/15 01:44, Jim Mooney wrote: > Why does the compiler choke on this? It seems to me that the enhanced > subtraction resolves to a legitimate integer That's your mistake. Assignment is a statement not an expression. It does not return anything. In fact its just illegal to try: >>> print x=3 File "", line 1 print x=3 ^ SyntaxError: invalid syntax >>> You have to do all the assignments up front. If you don;t need to store the new value you can just put the subtraction as an argument: sum += int(char) * 2**(start-1) But if you need start to hold that new value you must do that assignment before using it. BTW. This is 'A Good Thing' since it avoids a whole class of bug that is very common in languages like C and encourages breaking up complex statements into multiple lines which aids debugging, readability and maintenance. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Tue Apr 21 10:24:09 2015 From: __peter__ at web.de (Peter Otten) Date: Tue, 21 Apr 2015 10:24:09 +0200 Subject: [Tutor] calling a method directly References: Message-ID: Jim Mooney wrote: > Is there any difference between these two since they give the same result, > and when is the second preferred? > >>>> x = 'ABE' >>>> x.lower() > 'abe' >>>> str.lower(x) > 'abe' You may call str.lower() explicitly for subclasses of str. If the subclass overrides the lower() method there is a difference: >>> class MyStr(str): ... def lower(self): return "lower({!r})".format(self) ... >>> x = MyStr("ABC") >>> x.lower() "lower('ABC')" >>> str.lower(x) 'abc' I don't think the second form is ever preferred, but if you know in advance that you are dealing only with strings a lazy person may sometimes write str.lower instead of the more conventional def lower(s): return s.lower() >>> words = "abrufen anrufen Anrufer".split() >>> sorted(words) ['Anrufer', 'abrufen', 'anrufen'] >>> sorted(words, key=str.lower) ['abrufen', 'anrufen', 'Anrufer'] >>> sorted(words, key=lambda s: s.lower()) ['abrufen', 'anrufen', 'Anrufer'] The main disadvantage of invoking an unbound method is that it defeats "duck-typing" (the code works with every object that has a lower() method returning a string), and that is more common and more useful than you might think after reading the following example: >>> class Cow: ... def lower(self): return "moo" ... def __repr__(self): return "" ... >>> words.append(Cow()) Lisa provides the interface needed for the sort operation >>> sorted(words, key=lambda s: s.lower()) ['abrufen', 'anrufen', 'Anrufer', ] but is not exactly a str: >>> sorted(words, key=str.lower) Traceback (most recent call last): File "", line 1, in TypeError: descriptor 'lower' requires a 'str' object but received a 'Cow' Moo ;) From __peter__ at web.de Tue Apr 21 10:45:51 2015 From: __peter__ at web.de (Peter Otten) Date: Tue, 21 Apr 2015 10:45:51 +0200 Subject: [Tutor] Pun panic, was Re: calling a method directly References: Message-ID: Peter Otten wrote: >>>> class Cow: > ... def lower(self): return "moo" If you can't make sense of that: at the time of writing I thought that "lowering" was a synonym for "mooing". After a look into the dictionary it turns out to be "lowing", not "lowering". Sorry! From alan.gauld at btinternet.com Tue Apr 21 11:09:50 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 21 Apr 2015 10:09:50 +0100 Subject: [Tutor] Pun panic, was Re: calling a method directly In-Reply-To: References: Message-ID: On 21/04/15 09:45, Peter Otten wrote: > Peter Otten wrote: > >>>>> class Cow: >> ... def lower(self): return "moo" > > If you can't make sense of that: at the time of writing I thought that > "lowering" was a synonym for "mooing". After a look into the dictionary it > turns out to be "lowing", not "lowering". Sorry! :-) I thought you were just being a bit random! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Tue Apr 21 12:40:05 2015 From: davea at davea.name (Dave Angel) Date: Tue, 21 Apr 2015 06:40:05 -0400 Subject: [Tutor] introspection In-Reply-To: References: <85egneo8eh.fsf@benfinney.id.au> <5b61b455af3848c28968f0b83f176482@sonic.net> Message-ID: <55362905.2070204@davea.name> On 04/21/2015 01:21 AM, Danny Yoo wrote: > What's supposed to happen in this situation? > > > ########################################## > class Person(object): > def __init__(self): pass > > j = Person() > john = j > jack = j > ########################################## > > What single name should we get back from the single Person object > here? "j", "john", or "jack"? And what name should you get from the second Person() object created here? mylist = [Person(), Person(), Person()] -- DaveA From davea at davea.name Tue Apr 21 12:55:21 2015 From: davea at davea.name (Dave Angel) Date: Tue, 21 Apr 2015 06:55:21 -0400 Subject: [Tutor] enhanced subtration in an exponent In-Reply-To: References: Message-ID: <55362C99.4060505@davea.name> On 04/20/2015 08:44 PM, Jim Mooney wrote: > Why does the compiler choke on this? It seems to me that the enhanced > subtraction resolves to a legitimate integer in the exponent, but I get a > syntax error: > > B = '11011101' > sum = 0 > start = len(B) > for char in B: > sum += int(char) * 2**(start -= 1) ## syntax error > > print(sum) > As others have said, the augmented assignment, like the regular assignment, is not permissible inside an expression. It is a type of statement. You could solve this easily enough by: B = '11011101' sum = 0 start = len(B) for index, char in enumerate(B): sum += int(char) * 2**(start - index) print(sum) But I'd think that: B = '11011101' sum = 0 for char in B: sum = sum * 2 + int(char) print(sum) reads much better, as well as being much faster. -- DaveA From breamoreboy at yahoo.co.uk Tue Apr 21 13:31:53 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Tue, 21 Apr 2015 12:31:53 +0100 Subject: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2? In-Reply-To: <1793882820.317947.1429560312853.JavaMail.yahoo@mail.yahoo.com> References: <1793882820.317947.1429560312853.JavaMail.yahoo@mail.yahoo.com> Message-ID: On 20/04/2015 21:05, Albert-Jan Roskam wrote: > Hi, > > My Raspberry Pi 2 comes with Python 3.2 (and 2.7). I run some code that uses the datetime module but I get an error: > > "AttributeError: 'datetime.datetime' object has no attribute 'timestamp'". On https://docs.python.org/3/whatsnew/3.3.html I see: "New datetime.datetime.timestamp() method: Return POSIX timestamp corresponding to thedatetime instance." Is upgrading Python 3.3 or higher my only option, or is it somehow possible to use the newer version of the datetime library for Python 3.2? I do not want to modify the source code of the library that causes the error (pysolar). > > Thanks! > > > Regards, > > Albert-Jan > > Python is very strong in guaranteeing backward compatibility, so why not copy the 3.3 pure Python code to your 3.2 setup and see what happens? -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From breamoreboy at yahoo.co.uk Tue Apr 21 13:33:09 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Tue, 21 Apr 2015 12:33:09 +0100 Subject: [Tutor] bin to dec conversion puzzlement In-Reply-To: <854moao7ca.fsf@benfinney.id.au> References: <854moao7ca.fsf@benfinney.id.au> Message-ID: On 20/04/2015 21:47, Ben Finney wrote: > Jim Mooney writes: > >> I can't seem to get my head around this 'simple' book example of >> binary-to-decimal conversion, which goes from left to right: >> >> B = '11011101' >> I = 0 >> while B: >> I = I * 2 + int(B[0]) >> B = B[1:] >> >> print(I) >>>>> 221 > > That is, IMO, a needlessly confusing way to write that code. > > Whoever wrote it is clearly pleased with how clever it is; but > cleverness is almost always a property of *bad* code because it's > difficult to understand at a glance. That's the case here. > > One significant problem with the code as written is that it uses a > ?while? loop and mutates the list, where there's no point; it should > just iterate over items *from* the list without changing it. > > Another significant problem is that it uses moronically-short, > completely unexpressive names. This is Python not FORTRAN. > > Try this:: > > binary_text = '11011101' > result = 0 > > for binary_digit in binary_text: > # Accumulate powers of 2 for each digit. > result = result * 2 + int(binary_digit) > > print(result) > >> Both methods work but I just can't see how the first one does. Am I >> missing something obvious here? > > No, you were missing something needlessly obscured by the badly-written > code. Which book is this? I will be sure never to recommend it. > > Hope that helps. > I agree entirely so a big +1 from me. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From fomcl at yahoo.com Tue Apr 21 13:55:16 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Tue, 21 Apr 2015 11:55:16 +0000 (UTC) Subject: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2? In-Reply-To: References: Message-ID: <1286807158.508134.1429617316517.JavaMail.yahoo@mail.yahoo.com> ----- Original Message ----- > From: Mark Lawrence > To: tutor at python.org > Cc: > Sent: Tuesday, April 21, 2015 1:31 PM > Subject: Re: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2? > > On 20/04/2015 21:05, Albert-Jan Roskam wrote: > >> Hi, >> >> My Raspberry Pi 2 comes with Python 3.2 (and 2.7). I run some code that > uses the datetime module but I get an error: >> >> "AttributeError: 'datetime.datetime' object has no attribute > 'timestamp'". On https://docs.python.org/3/whatsnew/3.3.html I see: > "New datetime.datetime.timestamp() method: Return POSIX timestamp > corresponding to thedatetime instance." Is upgrading Python 3.3 or higher > my only option, or is it somehow possible to use the newer version of the > datetime library for Python 3.2? I do not want to modify the source code of the > library that causes the error (pysolar). >> >> Thanks! >> >> >> Regards, >> >> Albert-Jan >> >> > > Python is very strong in guaranteeing backward compatibility, so why not > copy the 3.3 pure Python code to your 3.2 setup and see what happens? Hmmm, nice idea. Never thought about that. Well, last night (before I saw your reply) I decided to download & compile Python 3.4, because I was afraid that this error might be the tip of the iceberg. Luckily, compiling the code went surprisingly fast on that little computer! I had to do it twice, though, because I got an error about _ssl (maybe with ensurepip?). I fixed it using "sudo apt-get install libssl-dev", but isn't the following the Offical Way (tm) to do this? Are there any more errors lurking in my Python 3.4 now? *) How do I find out the URL of the entry? pi at raspberrypi ~ $ sudo apt-get build-dep python3.4 Reading package lists... Done Building dependency tree Reading state information... Done E: You must put some 'source' URIs in your sources.list *) Argh, while writing this I can confirm that this is still not a good installation: pi at raspberrypi ~ $ python3.4 -c "import sqlite3" Traceback (most recent call last): File "", line 1, in File "/usr/local/lib/python3.4/sqlite3/__init__.py", line 23, in from sqlite3.dbapi2 import * File "/usr/local/lib/python3.4/sqlite3/dbapi2.py", line 27, in from _sqlite3 import * ImportError: No module named '_sqlite3' Probably this will work, but I will *never* be able to remember all these packages, so an entry in sources.list will be much nicer: https://github.com/yyuu/pyenv/wiki/Common-build-problems Best wishes, Albert-Jan From steve at pearwood.info Tue Apr 21 14:50:22 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 21 Apr 2015 22:50:22 +1000 Subject: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2? In-Reply-To: References: <1793882820.317947.1429560312853.JavaMail.yahoo@mail.yahoo.com> Message-ID: <20150421125022.GL5663@ando.pearwood.info> On Tue, Apr 21, 2015 at 12:31:53PM +0100, Mark Lawrence wrote: > Python is very strong in guaranteeing backward compatibility, so why not > copy the 3.3 pure Python code to your 3.2 setup and see what happens? Normally backwards compatibility refers to the other way: 3.3 will run 3.2 code. To have 3.2 run 3.3 code is *forward compatibility*. -- Steve From martin at linux-ip.net Tue Apr 21 16:09:51 2015 From: martin at linux-ip.net (Martin A. Brown) Date: Tue, 21 Apr 2015 07:09:51 -0700 Subject: [Tutor] Pun panic, was Re: calling a method directly In-Reply-To: References: Message-ID: Good morning underscore underscore Peter underscore underscore, >>>>> class Cow: >> ... def lower(self): return "moo" > > If you can't make sense of that: at the time of writing I thought > that "lowering" was a synonym for "mooing". After a look into the > dictionary it turns out to be "lowing", not "lowering". Sorry! I, too, assumed an amusingly random example. I simply imagined a maladjusted bovine Lisa suspended ominously beneath the clouds. Your Lisa must not be just a lowing (synonym 'mooing') cow, she must also be a lowering cow. to lower (v.i.), to be or become dark, gloomy, and threatening (which is cognate to the contemporary German word 'lauern') And, I dairy not chase this pun any further.... -Martin [0] http://www.merriam-webster.com/dictionary/lower -- Martin A. Brown http://linux-ip.net/ From marc.tompkins at gmail.com Tue Apr 21 18:23:19 2015 From: marc.tompkins at gmail.com (Marc Tompkins) Date: Tue, 21 Apr 2015 09:23:19 -0700 Subject: [Tutor] Pun panic, was Re: calling a method directly In-Reply-To: References: Message-ID: On Tue, Apr 21, 2015 at 7:09 AM, Martin A. Brown wrote: > And, I dairy not chase this pun any further.... > No - keep milking it. It gets butter all the time. From akleider at sonic.net Tue Apr 21 18:59:32 2015 From: akleider at sonic.net (Alex Kleider) Date: Tue, 21 Apr 2015 09:59:32 -0700 Subject: [Tutor] introspection In-Reply-To: References: <85egneo8eh.fsf@benfinney.id.au> <5b61b455af3848c28968f0b83f176482@sonic.net> Message-ID: <79ac40ca7483661a26e183d3c6a6b524@sonic.net> On 2015-04-20 22:21, Danny Yoo wrote: > What's supposed to happen in this situation? > > > ########################################## > class Person(object): > def __init__(self): pass > > j = Person() > john = j > jack = j > ########################################## > > What single name should we get back from the single Person object > here? "j", "john", or "jack"? I was hoping that it would be possible to create a function that would do the following: def my_name(some_object): return some_object.__name__ so, using what you entered above.. >>> my_name(j) 'j' >>> my_name(john) 'john' >>> my_name(jack) 'jack' But I see what I think you and others have been trying to explain to me: that the expression some_object.__name__, if it existed, would indeed be schizophrenic since it would be an attribute of the object, not the name(s) to which it is bound. Thanks all for your replies. ak From dyoo at hashcollision.org Tue Apr 21 19:20:45 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Tue, 21 Apr 2015 10:20:45 -0700 Subject: [Tutor] introspection In-Reply-To: <79ac40ca7483661a26e183d3c6a6b524@sonic.net> References: <85egneo8eh.fsf@benfinney.id.au> <5b61b455af3848c28968f0b83f176482@sonic.net> <79ac40ca7483661a26e183d3c6a6b524@sonic.net> Message-ID: > But I see what I think you and others have been trying to explain to me: > that the expression some_object.__name__, if it existed, would indeed be > schizophrenic since it would be an attribute of the object, not the name(s) > to which it is bound. The hypothetical feature might also, if designed badly, break simple things like checking for equality. e.g. say that we do: x = # ... some value y = copy.deepcopy(x) Would x == y? From my understanding, if the object were automatically associating a __name__, it should not. And that would be weird. :P This is not to say that what you're asking for is unreasonable! It's just that Python doesn't do it, and introducing such a feature in Python would have large implications in terms of what it means, not to mention how it might affect the runtime. From anton.garou at gmail.com Tue Apr 21 15:01:39 2015 From: anton.garou at gmail.com (Opher Lubzens) Date: Tue, 21 Apr 2015 16:01:39 +0300 Subject: [Tutor] handling exception raising in atexit registered function Message-ID: Hi, I am developing an automated testing script in python which will, among other things, send an email when it is done. For this I would like to send an email when an exception is raised as well - since it already has a cleanup function registered with atexit, this is the logical place to do it. However, I didn't find a good HOWTO on a cleanup function like that identifying an exception has been raised and reacting to it. thanks, Opher From cory.smith14 at outlook.com Tue Apr 21 13:17:23 2015 From: cory.smith14 at outlook.com (Ryan Scholes) Date: Tue, 21 Apr 2015 12:17:23 +0100 Subject: [Tutor] ?! Message-ID: Hi, Didn't really understand the instructions on the website but is this the right email address for help? Thanks, cory :) From memilanuk at gmail.com Tue Apr 21 20:26:33 2015 From: memilanuk at gmail.com (memilanuk) Date: Tue, 21 Apr 2015 11:26:33 -0700 Subject: [Tutor] ?! In-Reply-To: References: Message-ID: On 04/21/2015 04:17 AM, Ryan Scholes wrote: > Hi, > > Didn't really understand the instructions on the website but is this the right email address for help? > It can be... Some very smart, experienced and helpful folks here - some are even all three! ;) Generally speaking... they aren't going to do your (home) work for you... try to provide some code to show what you've tried, and specific questions as to what you're having trouble with. -- Shiny! Let's be bad guys. Reach me @ memilanuk (at) gmail dot com From alan.gauld at btinternet.com Tue Apr 21 20:51:53 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 21 Apr 2015 19:51:53 +0100 Subject: [Tutor] ?! In-Reply-To: References: Message-ID: On 21/04/15 12:17, Ryan Scholes wrote: > Didn't really understand the instructions on the website but is this the right email address for help? If its help about: a) learning to program b) learning the Python programming language c) learning the Python standard library Then yes, this is the right place. Ask questions. Tell us what OS you use, what version of Python and if you have an error message cut n paste it into the email. We will try to answer for you or at least point you in the right direction. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From ben+python at benfinney.id.au Wed Apr 22 01:27:02 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Wed, 22 Apr 2015 09:27:02 +1000 Subject: [Tutor] Pun panic References: Message-ID: <85lhhlm5a1.fsf_-_@benfinney.id.au> "Martin A. Brown" writes: > Good morning underscore underscore Peter underscore underscore, The Pythonic way to pronounce that would be ?dunder Pete dunder? . -- \ ?Geeks like to think that they can ignore politics. You can | `\ leave politics alone, but politics won't leave you alone.? | _o__) ?Richard M. Stallman, 2002-07-26 | Ben Finney From ben+python at benfinney.id.au Wed Apr 22 01:38:18 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Wed, 22 Apr 2015 09:38:18 +1000 Subject: [Tutor] introspection References: <85egneo8eh.fsf@benfinney.id.au> <5b61b455af3848c28968f0b83f176482@sonic.net> <79ac40ca7483661a26e183d3c6a6b524@sonic.net> Message-ID: <85fv7tm4r9.fsf@benfinney.id.au> Alex Kleider writes: > I was hoping that it would be possible to create a function > that would do the following: > > def my_name(some_object): > return some_object.__name__ That hope is understandable. It is also easy to be confused about why such a feature doesn't exist; after all, it works for functions and classes and modules (oh my!):: >>> def foo(): pass ... >>> foo.__name__ 'foo' >>> class Bar: pass ... >>> Bar.__name__ 'Bar' >>> import sys >>> sys.__name__ 'sys' So why not arbitrary objects? >>> spam = 4 >>> spam.__name__ Traceback (most recent call last): File "", line 1, in AttributeError: 'int' object has no attribute '__name__' The answer is that functions, classes, and modules are all *defined*, and (normally) have exactly one canonical name established at definition time. Arbitrary objects are merely *instantiated*, without that definition step. Quite commonly they are used with no name bound to them; so the behaviour of most objects does not have ?__name__? in the API. If you would like to make a class that has that attribute on all its instances, feel free. But you need to figure out how the instance detects its own name! class LockeanThing: """ An object that knows the name by which others refer to it. """ def __init__(self): self.__name__ = ??? > But I see what I think you and others have been trying to explain to > me: that the expression some_object.__name__, if it existed, would > indeed be schizophrenic since it would be an attribute of the object, > not the name(s) to which it is bound. That's why I prefer to be clear that the binding operation is one-way only. A reference (such as a name) is bound to an object, the object is not bound to the reference ? indeed, the object knows nothing about that relationship. -- \ ?I washed a sock. Then I put it in the dryer. When I took it | `\ out, it was gone.? ?Steven Wright | _o__) | Ben Finney From cs at zip.com.au Wed Apr 22 01:48:03 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 22 Apr 2015 09:48:03 +1000 Subject: [Tutor] introspection In-Reply-To: <79ac40ca7483661a26e183d3c6a6b524@sonic.net> References: <79ac40ca7483661a26e183d3c6a6b524@sonic.net> Message-ID: <20150421234803.GA37521@cskk.homeip.net> On 21Apr2015 09:59, Alex Kleider wrote: >On 2015-04-20 22:21, Danny Yoo wrote: >>What's supposed to happen in this situation? >>########################################## >>class Person(object): >> def __init__(self): pass >> >>j = Person() >>john = j >>jack = j >>########################################## >> >>What single name should we get back from the single Person object >>here? "j", "john", or "jack"? > >I was hoping that it would be possible to create a function >that would do the following: > >def my_name(some_object): > return some_object.__name__ > >so, using what you entered above.. >>>>my_name(j) >'j' >>>>my_name(john) >'john' >>>>my_name(jack) >'jack' > >But I see what I think you and others have been trying to explain to >me: that the expression some_object.__name__, if it existed, would >indeed be schizophrenic since it would be an attribute of the object, >not the name(s) to which it is bound. But it would not be schizophrenic to write a function that returned a name arbitrarily, by inspecting locals(). It depends whether you only need a name, or if you need "the" name. Write yourself a "find_name_from_locals(local_map, value)" function that reports. That will (a) get you a partial answer and (b) cement in your mind what is possible and why. Easy and useful! Cheers, Cameron Simpson Technique will get you through times of no strength a lot better than strength will get you through times of no technique. - the Nealomatic From cs at zip.com.au Wed Apr 22 01:59:51 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 22 Apr 2015 09:59:51 +1000 Subject: [Tutor] calling a method directly In-Reply-To: References: Message-ID: <20150421235951.GA61397@cskk.homeip.net> On 21Apr2015 09:03, alan.gauld at btinternet.com wrote: >On 21/04/15 05:19, Jim Mooney wrote: >>Is there any difference between these two since they give the same result, >>and when is the second preferred? >> >>>>>x = 'ABE' >>>>>x.lower() >>'abe' >>>>>str.lower(x) >>'abe' > >They are essentially the same method being accessed in two >different ways. >The first via the instance, >the second via the class. Though only because 'x' is directly a str. Not some other class. In Jim's example we _know_ 'x' is a str. In general one is less sure, and often one hopes not to care! >It's a bit like when you call a superclass method in OOP: >>>> class C: >... def f(s): print 'in C' >... >>>> class D(C): >... def f(s): >... C.f(s) >... print 'and D' >... def g(s): print 'only D' >... > >In the first line of D.f() you invoke C's foo method >by referring to C and passing the local self as the object. Worth pointing out that this is almost always the only time you cant to call via the class directly. And that it is actually common in subclass method implementations, particularly __init__, where on must often go: class D(C): def __init__(self, blah...): # initialise the common "C" class related stuff C.__init__(self, ...) # intialise the specific "D" class related stuff ... D-specific-stuff-here ... [...] >There are very few cases where the class version is preferred, >you nearly always use the instance technique. Indeed. Not least because (a) you don't always know or even care what class an object is and (b) objects themselves can have callable attributes. Cheers, Cameron Simpson Applications Programming is for dullards who can't do Systems Programming. - David Rose, dave at werple.apana.org.au From cs at zip.com.au Wed Apr 22 02:25:48 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 22 Apr 2015 10:25:48 +1000 Subject: [Tutor] Is it possible to "backport" the datetime module of Python 3.3 to Python 3.2? In-Reply-To: <20150421125022.GL5663@ando.pearwood.info> References: <20150421125022.GL5663@ando.pearwood.info> Message-ID: <20150422002548.GA33929@cskk.homeip.net> On 21Apr2015 22:50, Steven D'Aprano wrote: >On Tue, Apr 21, 2015 at 12:31:53PM +0100, Mark Lawrence wrote: > >> Python is very strong in guaranteeing backward compatibility, so why not >> copy the 3.3 pure Python code to your 3.2 setup and see what happens? > >Normally backwards compatibility refers to the other way: 3.3 will run >3.2 code. To have 3.2 run 3.3 code is *forward compatibility*. Yes, but it can depend on where you stand. Mark was talking about taking the 3.3 datetime module code and running it on 3.2. So in this context, he is suggesting that the _code_ in the 3.3 datetime module is probably backward compatible - it has presents features but does not depend on 3.3 aspects of the language, and therefore may well run on 3.2. Cheers, Cameron Simpson The most annoying thing about being without my files after our disc crash was discovering once again how widespread BLINK was on the web. From akleider at sonic.net Wed Apr 22 03:04:05 2015 From: akleider at sonic.net (Alex Kleider) Date: Tue, 21 Apr 2015 18:04:05 -0700 Subject: [Tutor] introspection In-Reply-To: <20150421234803.GA37521@cskk.homeip.net> References: <79ac40ca7483661a26e183d3c6a6b524@sonic.net> <20150421234803.GA37521@cskk.homeip.net> Message-ID: On 2015-04-21 16:48, Cameron Simpson wrote: > But it would not be schizophrenic to write a function that returned a > name arbitrarily, by inspecting locals(). It depends whether you only > need a name, or if you need "the" name. In my use case there'd probably be only one name for the given object so I believe you've given me my next exercise! > > Write yourself a "find_name_from_locals(local_map, value)" function > that reports. That will (a) get you a partial answer and (b) cement in > your mind what is possible and why. Easy and useful! I'll get working on that! > > Cheers, > Cameron Simpson > > Technique will get you through times of no strength a lot better than > strength will get you through times of no technique. - the > Nealomatic Wonderful quote by the way! From akleider at sonic.net Wed Apr 22 03:12:47 2015 From: akleider at sonic.net (Alex Kleider) Date: Tue, 21 Apr 2015 18:12:47 -0700 Subject: [Tutor] introspection In-Reply-To: <85fv7tm4r9.fsf@benfinney.id.au> References: <85egneo8eh.fsf@benfinney.id.au> <5b61b455af3848c28968f0b83f176482@sonic.net> <79ac40ca7483661a26e183d3c6a6b524@sonic.net> <85fv7tm4r9.fsf@benfinney.id.au> Message-ID: <507adf67fed517638a7530acc8f66764@sonic.net> On 2015-04-21 16:38, Ben Finney wrote: > That hope is understandable. > Your "understanding" is appreciated. > It is also easy to be confused .... So true, but with the help of "Python Tutors" things are being rectified! about why such a feature doesn't exist; > So why not arbitrary objects? > > The answer is that functions, classes, and modules are all *defined*, > and (normally) have exactly one canonical name established at > definition > time. > > Arbitrary objects are merely *instantiated*, without that definition > step. Quite commonly they are used with no name bound to them; so the > behaviour of most objects does not have ?__name__? in the API. > > If you would like to make a class that has that attribute on all its > instances, feel free. But you need to figure out how the instance > detects its own name! > > class LockeanThing: > """ An object that knows the name by which others refer to it. > """ > > def __init__(self): > self.__name__ = ??? > >> But I see what I think you and others have been trying to explain to >> me: that the expression some_object.__name__, if it existed, would >> indeed be schizophrenic since it would be an attribute of the object, >> not the name(s) to which it is bound. > > That's why I prefer to be clear that the binding operation is one-way > only. > > A reference (such as a name) is bound to an object, the object is not > bound to the reference ? indeed, the object knows nothing about that > relationship. It's sinking in. Thank you. ak From __peter__ at web.de Wed Apr 22 08:56:45 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 22 Apr 2015 08:56:45 +0200 Subject: [Tutor] Pun panic References: <85lhhlm5a1.fsf_-_@benfinney.id.au> Message-ID: Ben Finney wrote: > "Martin A. Brown" writes: > >> Good morning underscore underscore Peter underscore underscore, > > The Pythonic way to pronounce that would be ?dunder Pete dunder? > . > Hm, should I campaign for a peter() builtin? From ben+python at benfinney.id.au Wed Apr 22 09:28:43 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Wed, 22 Apr 2015 17:28:43 +1000 Subject: [Tutor] Pun panic References: <85lhhlm5a1.fsf_-_@benfinney.id.au> Message-ID: <85r3rcliz8.fsf@benfinney.id.au> Peter Otten <__peter__ at web.de> writes: > Ben Finney wrote: > > > The Pythonic way to pronounce that would be ?dunder Pete dunder? > > . > > Hm, should I campaign for a peter() builtin? You'll need a working implementation first. Put it on BullCodes for bonus Python-based free-software repository hosting points! -- \ ?I'm a born-again atheist.? ?Gore Vidal | `\ | _o__) | Ben Finney From fomcl at yahoo.com Wed Apr 22 11:03:50 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 22 Apr 2015 09:03:50 +0000 (UTC) Subject: [Tutor] Pun panic In-Reply-To: <85r3rcliz8.fsf@benfinney.id.au> References: <85lhhlm5a1.fsf_-_@benfinney.id.au> <85r3rcliz8.fsf@benfinney.id.au> Message-ID: <1782039505.901202.1429693431007.JavaMail.yahoo@mail.yahoo.com> ----- Original Message ----- > From: Ben Finney > To: tutor at python.org > Cc: > Sent: Wednesday, April 22, 2015 9:28 AM > Subject: Re: [Tutor] Pun panic > > Peter Otten <__peter__ at web.de> writes: > >> Ben Finney wrote: >> >> > The Pythonic way to pronounce that would be ?dunder Pete dunder? >> > . >> >> Hm, should I campaign for a peter() builtin? > > You'll need a working implementation first. Put it on BullCodes > for bonus Python-based free-software > repository hosting points! Is bull.codes better than Github or Bitbucket? Does it work with Travis CI and Appveyor? From breamoreboy at yahoo.co.uk Wed Apr 22 13:01:46 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 22 Apr 2015 12:01:46 +0100 Subject: [Tutor] Pun panic In-Reply-To: References: <85lhhlm5a1.fsf_-_@benfinney.id.au> Message-ID: On 22/04/2015 07:56, Peter Otten wrote: > Ben Finney wrote: > >> "Martin A. Brown" writes: >> >>> Good morning underscore underscore Peter underscore underscore, >> >> The Pythonic way to pronounce that would be ?dunder Pete dunder? >> . >> > > Hm, should I campaign for a peter() builtin? > Only if you provide an itertools version first :) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From ben+python at benfinney.id.au Wed Apr 22 14:40:15 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Wed, 22 Apr 2015 22:40:15 +1000 Subject: [Tutor] Pun panic References: <85lhhlm5a1.fsf_-_@benfinney.id.au> <85r3rcliz8.fsf@benfinney.id.au> <1782039505.901202.1429693431007.JavaMail.yahoo@mail.yahoo.com> Message-ID: <85mw20l4k0.fsf@benfinney.id.au> Albert-Jan Roskam writes: > ----- Original Message ----- > > From: Ben Finney > > You'll need a working implementation first. Put it on BullCodes > > for bonus Python-based free-software > > repository hosting points! > > Is bull.codes better than Github or Bitbucket? Yes, because those are not free software. Kallithea (which is what powers BullCodes) is free software, meaning anyone is free to see how it works and change it and run their own instance and share changes. > Does it work with Travis CI and Appveyor? Not until the Kallithea community adds that support. Since it is free software that's more likely than if it were proprietary :-) -- \ ?Reichel's Law: A body on vacation tends to remain on vacation | `\ unless acted upon by an outside force.? ?Carol Reichel | _o__) | Ben Finney From akleider at sonic.net Wed Apr 22 17:52:37 2015 From: akleider at sonic.net (Alex Kleider) Date: Wed, 22 Apr 2015 08:52:37 -0700 Subject: [Tutor] Pun panic In-Reply-To: <85mw20l4k0.fsf@benfinney.id.au> References: <85lhhlm5a1.fsf_-_@benfinney.id.au> <85r3rcliz8.fsf@benfinney.id.au> <1782039505.901202.1429693431007.JavaMail.yahoo@mail.yahoo.com> <85mw20l4k0.fsf@benfinney.id.au> Message-ID: <819536b8284f6656b4894d550c0e21e8@sonic.net> On 2015-04-22 05:40, Ben Finney wrote: > Albert-Jan Roskam writes: > >> ----- Original Message ----- >> > From: Ben Finney >> > You'll need a working implementation first. Put it on BullCodes >> > for bonus Python-based free-software >> > repository hosting points! >> >> Is bull.codes better than Github or Bitbucket? > > Yes, because those are not free software. > > > > Kallithea (which is what powers BullCodes) is free software, meaning > anyone is free to see how it works and change it and run their own > instance and share changes. > > There seems to be much documentation on how to set up Kallithea as a server, but I've been unable to find anything resembling a user (i.e. someone who wants to keep a project hosted on bull.code) 'howto' with regard to bull.code. Any suggestions? From ben+python at benfinney.id.au Wed Apr 22 21:22:24 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Thu, 23 Apr 2015 05:22:24 +1000 Subject: [Tutor] Pun panic References: <85lhhlm5a1.fsf_-_@benfinney.id.au> <85r3rcliz8.fsf@benfinney.id.au> <1782039505.901202.1429693431007.JavaMail.yahoo@mail.yahoo.com> <85mw20l4k0.fsf@benfinney.id.au> <819536b8284f6656b4894d550c0e21e8@sonic.net> Message-ID: <85egncklxr.fsf@benfinney.id.au> Alex Kleider writes: > On 2015-04-22 05:40, Ben Finney wrote: > > > > > > Kallithea (which is what powers BullCodes) is free software, meaning > > anyone is free to see how it works and change it and run their own > > instance and share changes. > > > > > > [?] I've been unable to find anything resembling a user (i.e. someone > who wants to keep a project hosted on bull.code) 'howto' with regard > to bull.code. Any suggestions? I don't think BullCodes has a pointer to it yet, but: Kallithea's documentation contains a ?General Kallithea usage? section , is that what you're looking for? -- \ ?I have always wished for my computer to be as easy to use as | `\ my telephone; my wish has come true because I can no longer | _o__) figure out how to use my telephone.? ?Bjarne Stroustrup | Ben Finney From fomcl at yahoo.com Wed Apr 22 22:55:01 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 22 Apr 2015 20:55:01 +0000 (UTC) Subject: [Tutor] Pun panic In-Reply-To: <85mw20l4k0.fsf@benfinney.id.au> References: <85lhhlm5a1.fsf_-_@benfinney.id.au> <85r3rcliz8.fsf@benfinney.id.au> <1782039505.901202.1429693431007.JavaMail.yahoo@mail.yahoo.com> <85mw20l4k0.fsf@benfinney.id.au> Message-ID: <1198498885.1157677.1429736101932.JavaMail.yahoo@mail.yahoo.com> ----- Original Message ----- > From: Ben Finney > To: tutor at python.org > Cc: > Sent: Wednesday, April 22, 2015 2:40 PM > Subject: Re: [Tutor] Pun panic > > Albert-Jan Roskam writes: > >> ----- Original Message ----- >> > From: Ben Finney >> > You'll need a working implementation first. Put it on BullCodes >> > for bonus Python-based free-software >> > repository hosting points! >> >> Is bull.codes better than Github or Bitbucket? > > Yes, because those are not free software. > > > > Kallithea (which is what powers BullCodes) is free software, meaning > anyone is free to see how it works and change it and run their own > instance and share changes. > > Cool, though it appears to be just starting. We use Gitbucket (with a G): https://github.com/takezoe/gitbucket. It's a Github clone, very easy to install (trivial), written in Scala. From akleider at sonic.net Thu Apr 23 03:29:37 2015 From: akleider at sonic.net (Alex Kleider) Date: Wed, 22 Apr 2015 18:29:37 -0700 Subject: [Tutor] Pun panic In-Reply-To: <85egncklxr.fsf@benfinney.id.au> References: <85lhhlm5a1.fsf_-_@benfinney.id.au> <85r3rcliz8.fsf@benfinney.id.au> <1782039505.901202.1429693431007.JavaMail.yahoo@mail.yahoo.com> <85mw20l4k0.fsf@benfinney.id.au> <819536b8284f6656b4894d550c0e21e8@sonic.net> <85egncklxr.fsf@benfinney.id.au> Message-ID: <862a36f579f265aa06dd199e3f80cd31@sonic.net> On 2015-04-22 12:22, Ben Finney wrote: > Alex Kleider writes: > >> On 2015-04-22 05:40, Ben Finney wrote: >> > >> > >> > Kallithea (which is what powers BullCodes) is free software, meaning >> > anyone is free to see how it works and change it and run their own >> > instance and share changes. >> > >> > >> >> [?] I've been unable to find anything resembling a user (i.e. someone >> who wants to keep a project hosted on bull.code) 'howto' with regard >> to bull.code. Any suggestions? > > I don't think BullCodes has a pointer to it yet, but: Kallithea's > documentation contains a ?General Kallithea usage? section > , is > that what you're looking for? I already looked through that page and indeed perhaps the information is there but not in a way that I can understand. No where can I find what steps to take to push a git repository that I have on my lap top to bullcode. But perhaps this is the wrong venue since it isn't Python related. Sorry. From cybervigilante at gmail.com Thu Apr 23 07:18:31 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Wed, 22 Apr 2015 22:18:31 -0700 Subject: [Tutor] name shortening in a csv module output Message-ID: I'm trying the csv module. It all went well until I tried shortening a long first name I put in just to exercise things. It didn't shorten. And I also got weird first characters on the header line. What went wrong? import csv allcsv = [] with open('data.txt') as csvfile: readCSV = csv.reader(csvfile, delimiter='|') topline = next(readCSV) topline[0] = topline[0].replace('_', ' ').title() topline[1] = topline[1].replace('_', ' ').title() print("{0:<20s} {1:<20s}".format(topline[0], topline[1])) print('==================================') for line in readCSV: if len(line[0]) > 40: # problem here - didn't shorten line[0] = line[0][:40] print("{0:<20s} {1:<20s}".format(line[0], line[1])) Original file lines: first_name|last_name|email|city|state or region|address|zip Stewartrewqrhjeiwqhreqwhreowpqhrueqwphruepqhruepqwhruepwhqupr|Dorsey|nec.malesuada at Quisqueporttitoreros.com|Cariboo Regional District|BC|P.O. Box 292, 8945 Nulla Avenue|5945 Madonna|Sosa|senectus.et at eget.ca|Belford Roxo|Rio de Janeiro|P.O. Box 538, 4484 Sem Avenue|81833 Duncan|Hutchinson|Donec.vitae at Integer.co.uk|Dublin|Leinster|Ap #847-2344 Feugiat. St.|9222 ... My result: ???First Name Last Name # odd characters on header line ================================== Stewartrewqrhjeiwqhreqwhreowpqhrueqwphru Dorsey Madonna Sosa Duncan Hutchinson ... -- Jim No comment From __peter__ at web.de Thu Apr 23 10:42:40 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 23 Apr 2015 10:42:40 +0200 Subject: [Tutor] name shortening in a csv module output References: Message-ID: Jim Mooney wrote: > I'm trying the csv module. It all went well until I tried shortening a > long first name I put in just to exercise things. It didn't shorten. > Original file lines: > Stewartrewqrhjeiwqhreqwhreowpqhrueqwphruepqhruepqwhruepwhqupr|Dorsey| nec.malesuada at Quisqueporttitoreros.com|Cariboo > My result: > Stewartrewqrhjeiwqhreqwhreowpqhrueqwphru Dorsey It did shorten: >>> len("Stewartrewqrhjeiwqhreqwhreowpqhrueqwphruepqhruepqwhruepwhqupr") 61 >>> len("Stewartrewqrhjeiwqhreqwhreowpqhrueqwphru") 40 > if len(line[0]) > 40: # problem here - didn't shorten > line[0] = line[0][:40] > print("{0:<20s} {1:<20s}".format(line[0], line[1])) You have to make up your mind if you want to shortend to 40 or 20 chars. > And I also got weird first characters on the header line. What went wrong? > Original file lines: > > first_name|last_name|email|city|state or region|address|zip ... > My result: > > ???First Name Last Name # odd characters on header line ... ??? is the UTF-8 BOM (byte order mark) interpreted as Latin 1. If the input is UTF-8 you can get rid of the BOM with with open("data.txt", encoding="utf-8-sig") as csvfile: ... From cybervigilante at gmail.com Thu Apr 23 12:37:11 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 23 Apr 2015 03:37:11 -0700 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: Message-ID: .. > ??? > > is the UTF-8 BOM (byte order mark) interpreted as Latin 1. > > If the input is UTF-8 you can get rid of the BOM with > > with open("data.txt", encoding="utf-8-sig") as csvfile: > Peter Otten I caught the bad arithmetic on name length, but where is the byte order mark coming from? My first line is plain English so far as I can see - no umlauts or foreign characters. first_name|last_name|email|city|state or region|address|zip Is this an artifact of csv module output, or is it the data from generatedata.com, which looks global? More likely it means I have to figure out unicode ;'( From __peter__ at web.de Thu Apr 23 14:05:31 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 23 Apr 2015 14:05:31 +0200 Subject: [Tutor] name shortening in a csv module output References: Message-ID: Jim Mooney wrote: > .. > >> ??? >> >> is the UTF-8 BOM (byte order mark) interpreted as Latin 1. >> >> If the input is UTF-8 you can get rid of the BOM with >> >> with open("data.txt", encoding="utf-8-sig") as csvfile: >> > > Peter Otten > > I caught the bad arithmetic on name length, but where is the byte order > mark coming from? Did you touch the data with an editor? That might be the culprit. > My first line is plain English so far as I can see - no > umlauts or foreign characters. > first_name|last_name|email|city|state or region|address|zip > > Is this an artifact of csv module output, or is it the data from > generatedata.com, which looks global? More likely it means I have to > figure out unicode ;'( From d at davea.name Thu Apr 23 16:29:42 2015 From: d at davea.name (Dave Angel) Date: Thu, 23 Apr 2015 10:29:42 -0400 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: Message-ID: <553901D6.90006@davea.name> On 04/23/2015 06:37 AM, Jim Mooney wrote: > .. > >> ??? >> >> is the UTF-8 BOM (byte order mark) interpreted as Latin 1. >> >> If the input is UTF-8 you can get rid of the BOM with >> >> with open("data.txt", encoding="utf-8-sig") as csvfile: >> > > Peter Otten > > I caught the bad arithmetic on name length, but where is the byte order > mark coming from? My first line is plain English so far as I can see - no > umlauts or foreign characters. > first_name|last_name|email|city|state or region|address|zip > > Is this an artifact of csv module output, or is it the data from > generatedata.com, which looks global? More likely it means I have to figure > out unicode ;'( A file is always stored as bytes, so if it's a text file, it is always an encoded file (although if it's ASCII, you tend not to think of that much). So whatever program writes that file has picked an encoding, and when you read it you have to use the same encoding to safely read it into text. By relying on the default when you read it, you're making an unspoken assumption about the encoding of the file. There are dozens of common encodings out there, and anytime you get the wrong one, you're likely to mess up somewhere, unless it happens to be pure ASCII. The BOM is not supposed to be used in a byte encoded file, but Notepad, among other programs does. So it happens to be a good clue that the rest of the file is encoded in utf-8. If that's the case, and if you want to strip the BOM, use utf-8-sig. Note: the BOM may be legal in utf-8 now, but it was originally intended to distinguish the UTF-32-BE from UTF-32-LE, as well as UTF-16-BE from UTF-16-LE. https://docs.python.org/2/library/codecs.html#encodings-and-unicode -- DaveA From cybervigilante at gmail.com Thu Apr 23 20:14:52 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 23 Apr 2015 11:14:52 -0700 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <553901D6.90006@davea.name> References: <553901D6.90006@davea.name> Message-ID: > > By relying on the default when you read it, you're making an unspoken > assumption about the encoding of the file. > > -- > DaveA So is there any way to sniff the encoding, including the BOM (which appears to be used or not used randomly for utf-8), so you can then use the proper encoding, or do you wander in the wilderness? I was going to use encoding = utf-8 as a suggested default. I noticed it got rid of the bom symbols but left an extra blank space at the beginning of the stream. Most books leave unicode to the very end, if they mention the BOM at all (mine is at page 977, which is still a bit off ;') From breamoreboy at yahoo.co.uk Thu Apr 23 23:08:05 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Thu, 23 Apr 2015 22:08:05 +0100 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: On 23/04/2015 19:14, Jim Mooney wrote: >> >> By relying on the default when you read it, you're making an unspoken >> assumption about the encoding of the file. >> >> -- >> DaveA > > > So is there any way to sniff the encoding, including the BOM (which appears > to be used or not used randomly for utf-8), so you can then use the proper > encoding, or do you wander in the wilderness? I was going to use encoding = > utf-8 as a suggested default. I noticed it got rid of the bom symbols but > left an extra blank space at the beginning of the stream. Most books leave > unicode to the very end, if they mention the BOM at all (mine is at page > 977, which is still a bit off ;') > I'm hardly an expert in the encoding field but I've heard this https://pypi.python.org/pypi/chardet is highly recommended. Slight aside, why a BOM, all I ever think of is Inspector Clouseau? :) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From alan.gauld at btinternet.com Thu Apr 23 23:09:50 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 23 Apr 2015 22:09:50 +0100 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: On 23/04/15 19:14, Jim Mooney wrote: >> >> By relying on the default when you read it, you're making an unspoken >> assumption about the encoding of the file. > > So is there any way to sniff the encoding, including the BOM (which appears > to be used or not used randomly for utf-8), so you can then use the proper > encoding, or do you wander in the wilderness? Pretty much guesswork. The move from plain old ASCII to Unicode (and others) has made the handling of text much more like binary. You have to know the binary format/encoding to know how to decode binary data. Its the same with text, if you don't know what produced it, and in what format, then you have to guess. There are some things you can do to check your results (such as try spell checking the results) and you can try checking the characters against the Unicode mappings to see if the sequences look sane. (for example a lot of mixed alphabets - like arabic, greek and latin - suggests you guessed wrong!) But none of it is really reliable. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Thu Apr 23 23:30:43 2015 From: davea at davea.name (Dave Angel) Date: Thu, 23 Apr 2015 17:30:43 -0400 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: <55396483.5080803@davea.name> On 04/23/2015 02:14 PM, Jim Mooney wrote: >> >> By relying on the default when you read it, you're making an unspoken >> assumption about the encoding of the file. >> >> -- >> DaveA > > > So is there any way to sniff the encoding, including the BOM (which appears > to be used or not used randomly for utf-8), so you can then use the proper > encoding, or do you wander in the wilderness? I was going to use encoding = > utf-8 as a suggested default. I noticed it got rid of the bom symbols but > left an extra blank space at the beginning of the stream. Most books leave > unicode to the very end, if they mention the BOM at all (mine is at page > 977, which is still a bit off ;') That's not a regular blank, See the link I mentioned before, and the following sentence: """ Unfortunately the character U+FEFF had a second purpose as a ZERO WIDTH NO-BREAK SPACE: a character that has no width and doesn?t allow a word to be split. It can e.g. be used to give hints to a ligature algorithm. """ To automatically get rid of that BOM character when reading a file, you use utf-8-sig, rather than utf-8. And on writing, since you probably don't want it, use utf-8. As for guessing what encoding was used, the best approach is to ask the person/program that wrote the file. Or read the specs. And once you figure it out, fix the specs. With a short sample, you're unlikely to guess right. That's because ASCII looks the same in all the byte-encoded formats. (Not in the various *16* and *32* formats, as they use 2 bytes or 4 bytes each) If you encounter one of those, you'll probably see lots of null bytes mixed in a consistent pattern. Consider the 'file' command in Linux. I don't know of any Windows equivalent. If you want to write your own utility, perhaps to scan hundreds of files, consider: http://pypi.python.org/pypi/chardet http://linux.die.net/man/3/libmagic https://github.com/ahupp/python-magic -- -- DaveA From davea at davea.name Thu Apr 23 23:40:34 2015 From: davea at davea.name (Dave Angel) Date: Thu, 23 Apr 2015 17:40:34 -0400 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: <553966D2.8070809@davea.name> On 04/23/2015 05:08 PM, Mark Lawrence wrote: > > Slight aside, why a BOM, all I ever think of is Inspector Clouseau? :) > As I recall, it stands for "Byte Order Mark". Applicable only to multi-byte storage formats (eg. UTF-16), it lets the reader decide which of the formats were used. For example, a file that reads fe ff 41 00 42 00 might be a big-endian version of UTF-16 while ff fe 00 41 00 42 might be the little-endian version of the same data. I probably have it all inside out and backwards, but that's the general idea. If the BOM appears backwards, you switch between BE and LE and the data will make sense. The same concept was used many years ago in two places I know of. Binary files representing faxes had "II" or "MM" at the beginning. But the UCSD-P system program format used a number (I think it was 0001) which would decode wrong if you were on the wrong processor type. The idea was that instead of coding an explicit check, you just looked at one piece of data, and if it was wrong, you had to swap all the byte-pairs. That way if you read the file on the same machine, no work was needed at all. Seems to me the Java bytecode does something similar, but I don't know. All of these are from memory, and subject to mis-remembering. -- DaveA From alan.gauld at btinternet.com Fri Apr 24 01:33:57 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 24 Apr 2015 00:33:57 +0100 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: <55398165.3050401@btinternet.com> On 24/04/15 00:15, Jim Mooney wrote: > Pretty much guesswork. > Alan Gauld > -- > This all sounds suspiciously like the old browser wars Its more about history. Early text encodings all worked in a single byte which is limited to 256 patterns. That's simply not enough to cover all the alphabets around. So people developed their own encodings for every computer platform, printer, county and combinations thereof. Unicode is an attempt to get away from that, but the historical junk is still out there. And unicode is not yet the de-facto standard. Now the simple thing to do would be just have one enormous character set that covers everything. That's Unicode 32 bit encoding. The snag is that it takes 4 bytes for every character, which is a lot of space/bandwidth. So more efficient encodings were introduced such as Unicode "16 bit" and "8 bit", aka utf-8. UTF-8 is becoming a standard but it has the complication that its a variable width standard where a character can be anything from a single byte up to 4 bytes long. The "rarer" the character the longer its encoding. And unfortunately the nature of the coding is such that it looks a lot like other historical encodings, especially some of the Latin ones. So you can get something almost sane out of a text by decoding it as utf8 but not quite totally sane. And it maybe some time into your usage before you realise you are actually using the wrong code! -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Fri Apr 24 02:09:54 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 24 Apr 2015 10:09:54 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: Message-ID: <20150424000953.GQ5663@ando.pearwood.info> On Wed, Apr 22, 2015 at 10:18:31PM -0700, Jim Mooney wrote: > My result: > > ???First Name Last Name # odd characters on header line Any time you see "odd characters" in text like that, you should immediately think "encoding problem". These odd characters are normally called mojibake, a Japanese term, or sometimes gremlins. Mojibake occurs when your text file was written in one encoding but then read back using another, e.g.: * file was written using a Windows code page, but read back on a different PC using a different code page (say, Greek then Russian); * file was written on a classic Macintosh (pre-OS X), then read on a DOS or Windows machine; * file was written on a mainframe that uses ASCII and transferred to a mainframe that uses EBCDIC; * file was written using an editor that defaults to one encoding, and read back using an editor that defaults to a different encoding; * HTML web page was saved using one encoding, but not declared (or declared wrongly) and the browser defaults to a different encoding. Sadly, this problem is hard to solve because text files can't, in general, contain metadata that tells you how the text is stored. We're reduced to conventions, hints, and guesses. Given that, the fact that there is so little mojibake in the world compared to how much there could be is astonishing. In your case, those specific three characters ??? found at the start of a text file indicates that the text file was saved by Notepad on Windows. For no good reason (although I'm sure it seemed like a good idea at the time, if they were smoking crack at the time), Notepad sometimes puts a UTF-8 signature at the start of text files. Actually Notepad tries to be way too clever but isn't clever enough: http://en.wikipedia.org/wiki/Bush_hid_the_facts ? This UTF-8 signature is sometimes called a "Byte Order Mark", or BOM, which is a misnomer. The solution is to use the utf-8-sig encoding instead of utf-8. -- Steve From steve at pearwood.info Fri Apr 24 03:29:38 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 24 Apr 2015 11:29:38 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: <20150424012938.GR5663@ando.pearwood.info> On Thu, Apr 23, 2015 at 10:08:05PM +0100, Mark Lawrence wrote: > Slight aside, why a BOM, all I ever think of is Inspector Clouseau? :) :-) I'm not sure if you mean that as an serious question or not. BOM stands for Byte Order Mark, and it if needed for UTF-16 and UTF-32 encodings because there is some ambiguity due to hardware differences. UTF-16 uses two byte "code units", that is, each character is represented by two bytes (or four, but we can ignore that). Similarly, UTF-32 uses four byte code units. The problem is, different platforms link multiple bytes in opposite order: "big-endian" and "little-endian". (In the Bad Old Days, there were "middle-endian" platforms too, and you really don't want to know about them.) For example, the two-byte quantity O1FE (in hex) might have: (1) the 01 byte at address 100 and the FE byte at address 101 (big end first) (2) the 01 byte at address 101 and the FE byte at address 100 (little end first) We always write the two bytes as 01FE in hexadecimal notation, with the "little end" (units) on the right, just as we do with decimals: 01FE = E units + F sixteens + 1 sixteen-squares + 0 sixteen-cubes is the same as 510 in decimal: 510 = 0 units + 1 ten + 5 ten-squares but in computer memory those two bytes could be stored either big-end first: 01 has the lower address FE has the higher address or little-end first: FE has the lower address 01 has the higher address So when you read a text file, and you see two bytes 01FE, unless you know whether that came from a big-endian system or a little-endian system, you don't know how to interpret it: - If both the sender and the receiver are big-endian, or little-endian, then two bytes 01 followed by FE represent 01FE or 510 in decimal, which is LATIN CAPITAL LETTER O WITH STROKE AND ACUTE in UTF-16. - If the sender and the receiver are opposite endians (one big-, the other little-, it doesn't matter which) then the two bytes 01 followed by FE will be seen as FE01 (65025 in decimal) which is VARIATION SELECTOR-2 in UTF-16. I've deliberately used the terms "sender" and "receiver", because this problem is fundamental to networking too. Whenever you transfer data from a Motorola based platform to an Intel based platform, the byte order has to be swapped like this. If it's not swapped, the data looks weird. (TIFF files also have to take endian issues into account.) UTF-16 and UTF-32 solve this problem by putting a Byte Order Mark at the start of the file. The BOM is two bytes in the case of UTF-16 (a single code-unit): py> ''.encode('utf-16') b'\xff\xfe' So when you read a UTF-16 file back, if it starts with two bytes FFFE (in hex), you can continue. If it starts with FEFF, then the bytes have been reversed. If you treat the file as Latin-1 (one of the many versions of "extended ASCII"), then you will see the BOM as either: ?? # byte order matches ?? # byte order doesn't match Normally you don't need to care about any of this! The encoding handles all the gory details. You just pick the right encoding: - UTF-16 if the file will have a BOM; - UTF-16BE if it is big-endian, and doesn't have a BOM; - UTF-16LE if it is little-endian, and doesn't have a BOM; and the encoding deals with the BOM. -- Steve From steve at pearwood.info Fri Apr 24 03:55:59 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 24 Apr 2015 11:55:59 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <553966D2.8070809@davea.name> References: <553901D6.90006@davea.name> <553966D2.8070809@davea.name> Message-ID: <20150424015558.GS5663@ando.pearwood.info> On Thu, Apr 23, 2015 at 05:40:34PM -0400, Dave Angel wrote: > On 04/23/2015 05:08 PM, Mark Lawrence wrote: > > > >Slight aside, why a BOM, all I ever think of is Inspector Clouseau? :) > > > > As I recall, it stands for "Byte Order Mark". Applicable only to > multi-byte storage formats (eg. UTF-16), it lets the reader decide > which of the formats were used. > > For example, a file that reads > > fe ff 41 00 42 00 > > might be a big-endian version of UTF-16 > > while > ff fe 00 41 00 42 > > might be the little-endian version of the same data. Almost :-) You have the string ")*", two characters. In ASCII, Latin-1, Mac-Roman, UTF-8, and many other encodings, that is represented by two code points. I'm going to use "U+ hex digits" as the symbol for code points, to distinguish them from raw bytes which won't use the U+ prefix. string ")*" gives code points U+41 U+42 They get written out to a single byte each, and so we get 41 42 as the sequence of bytes (still written in hex). In UTF-16, those two characters are represented by the same two code points, *but* the "code unit" is two bytes rather than one: U+0041 U+0042 with leading zeroes included. Each code unit gets written out as a two-byte quantity: On little-endian systems like Intel hardware: 4100 4200 On big-endian systems like Motorola hardware: 0041 0042 Insert the BOM, which is always code point U+FEFF: On little-endian systems: FFFE 4100 4200 On big-endian systems: FEFF 0041 0042 If you take that file and read it back as Latin-1, you get: little-endian: ??A\0B\0 big-endian: ??\0A\0B Notice the \0 nulls? Your editor might complain that the file is a binary file, and refuse to open it, unless you tell the editor it is UTF-16. > The same concept was used many years ago in two places I know of. > Binary files representing faxes had "II" or "MM" at the beginning. Yes, TIFF files use a similar scheme. You get them starting with a signature TIFF or FFTI, I believe. -- Steve From steve at pearwood.info Fri Apr 24 04:46:20 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 24 Apr 2015 12:46:20 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <55398165.3050401@btinternet.com> References: <553901D6.90006@davea.name> <55398165.3050401@btinternet.com> Message-ID: <20150424024619.GT5663@ando.pearwood.info> On Fri, Apr 24, 2015 at 12:33:57AM +0100, Alan Gauld wrote: > On 24/04/15 00:15, Jim Mooney wrote: > >Pretty much guesswork. > >Alan Gauld > >-- > >This all sounds suspiciously like the old browser wars > > Its more about history. Early text encodings all worked in a single byte > which is > limited to 256 patterns. Oh it's much more complicated than that! The first broadly available standard encoding was ASCII, which was *seven bits*, not even a full byte. It was seven bits so that there was an extra bit available for error correction when sending over telex or some such thing. (There were other encodings older than ASCII, like EBCDIC, which was used on IBM mainframes and is either 7 or 8 bits.) With seven bits, you can only have 127 characters. About 30 odd are used for control characters (which used to be important, now only two or three of them are still commonly used, but we're stuck with them forever), so ASCII is greatly impoverished, even for American English. (E.g. there is no cent symbol.) Hence the 1970s through 90s saw an explosion of "code pages" for Windows systems, national standards which extended ASCII to use a full 8 bits (plus a few 16-bit and variable-bit standards as well). Fortunately people rarely swapped documents from one platform to another. Then, in the late 1990s, Internet access started becoming common, and what do people do on the Internet? They exchange files. Chaos and confusion everywhere... > That's simply not enough to cover all the > alphabets > around. So people developed their own encodings for every computer > platform, > printer, county and combinations thereof. Unicode is an attempt to get away > from that, but the historical junk is still out there. And unicode is > not yet > the de-facto standard. Not quite. Unicode is an actual real standard, and pretty much everyone agrees that it is the only reasonable choice[1] as a standard. It is quite close to being a standard in practice as well as on paper: Unicode is more or less the language of the Internet, something like 85% of web pages now use UTF-8, Linux and Mac desktops use UTF-8, Windows provides optional Unicode interfaces for their programming APIs, most modern languages (with the exception of PHP, what a surprise) provide at least moderate Unicode support. Sadly though you are right that there are still historical documents to deal with and (mostly Windows) systems which even today still default to using legacy encodings rather than Unicode. We'll be dealing with legacy encodings for decades, especially since East Asian countries lag behind the West for Unicode adoption, but Unicode has won. > Now the simple thing to do would be just have one enormous character > set that covers everything. That's Unicode 32 bit encoding. No it isn't :-) The character set and the encoding are *not the same*. We could have a two-character set with a 32-bit encoding, if we were nuts: Two characters only: A and B A encodes as four bytes 00 00 00 00 B encodes as four bytes FF FF FF FF and every other combination of bytes is an error. The set of characters provided by Unicode is the same regardless of how those characters are encoded to and from bytes. The official standard is the "Universal Character Set", or UCS, which supports 1114112 different "code points", numbered from U+0000 to U+10FFFF. Each code point represents: - a character (letter, digit, symbol, etc.) - control character - private-use characters - reserved for future use - non-characters (e.g. BOM, variation selectors, surrogates) - combining accents etc. Unicode can be considered the same as UCS plus a bunch of other stuff, such as rules for sorting. Notice that UCS and Unicode deliberately use much less than the full 4294967296 possible values of a 32-bit quantity. You can fit Unicode in 21 bits. Historically, the UCS started at 16 bits, it may have reserved the full 32 bits, but it is now guaranteed to use no more than 21 bits U+10FFFF will be the highest code point forever. > The snag is > that it takes 4 bytes for every character, which is a lot of > space/bandwidth. > So more efficient encodings were introduced such as Unicode "16 bit" and > "8 bit", aka utf-8. Historically, the Universal Character Set and Unicode originally was only 16 bit, so the first UCS encoding was UCS-2, which uses two bytes for every code point. But they soon realised that they needed more than 65536 code points, and UCS-2 is now obsolute. The current version of Unicode and UCS uses 21 bits, and guaranteed that there will be no future expansions. They include a bunch of encodings: UCS-4 uses a full 32-bits per code point; it is defined in the UCS standard. UTF-32 does the same, except in the Unicode standard. They are effectively identical, just different names because they live in different standards. UTF-16 is a variable-width encoding, using either 2 bytes or 4. It is effectively an extension to the obsolete UCS-2. UTF-8 is a variable-width encoding, using 1, 2, 3, or 4 bytes. The mechanism works for up to six bytes, but the standard guarantees that it will never exceed 4 bytes. UTF-7 is a "seven-bit clean" version, for systems which cannot deal with text data with the high-bit set. There are a few others in the various standards, but nobody uses them :-) > UTF-8 is becoming a standard but it has the complication that its a > variable > width standard where a character can be anything from a single byte up > to 4 bytes long. The "rarer" the character the longer its encoding. And > unfortunately the nature of the coding is such that it looks a lot like > other historical encodings, especially some of the Latin ones. So you can > get something almost sane out of a text by decoding it as utf8 but not > quite totally sane. And it maybe some time into your usage before you > realise you are actually using the wrong code! That's by design! If you use nothing but ASCII characters, then UTF-8 and ASCII are identical. If you save a text file "Hello World!" using any of the other UTF encodings (UTF-16, -32 in particular), you will get something which an old, dumb non-Unicode aware application cannot deal with. It will treat it as a binary file, because it contains lots of zero bytes. C programs will choke on it. But with UTF-8, so long as you limit yourself to only ASCII characters, old ASCII programs will continue to work fine. This was a very important requirement that allowed Unicode to become popular. Editors can ship defaulting to UTF-8, and so long as their users only type ASCII characters other non-Unicode programs won't know the difference. [1] There are a very few people in Japan who use TRON instead, because TRON separates Japanese characters from their identical Chinese and Korean characters -- think about having a separate English A, French A and German A. Pretty much nobody else uses it, and precious few Japanese. It's not quite 100% due to Japanese nationalism, there are some good reasons for wanting to separate the characters, but it's probably 97% Japanese nationalism. The Japanese, Chinese and Korean governments, as well as linguists, are all in agreement that despite a few minor differences, the three languages share a common character set. -- Steve From cybervigilante at gmail.com Fri Apr 24 01:15:39 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 23 Apr 2015 16:15:39 -0700 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: So is there any way to sniff the encoding, including the BOM (which appears to be used or not used randomly for utf-8), so you can then use the proper encoding, or do you wander in the wilderness? Pretty much guesswork. > Alan Gauld -- This all sounds suspiciously like the old browser wars I suffered while webmastering. I'd almost think Microsoft had a hand in it ;') If utf-8 can handle a million characters, why isn't it just the standard? I doubt we'd need more unless the Martians land. Since I am reading opinions that the BOM doesn't even belong in utf-8, can I assume just using utf-8-sig as my default encoding, even on a non-BOM file, would do no harm? Jim From cybervigilante at gmail.com Fri Apr 24 04:37:56 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Thu, 23 Apr 2015 19:37:56 -0700 Subject: [Tutor] Spongebob Pythonpants Message-ID: I was depressed at the thought of learning unicode, then discovered Python was fun again since I can easily print any ascii art from http://www.chris.com/ascii/ with a multiline print, so long as I replace any backslash with two of them. Spongebob Squarepants was, of course, the obvious first choice. The heck with Tkinter. (Bob is coming out a bit thin in my gmail but looks fine in the REPL.) print(''' .--..--..--..--..--..--. .' \\ (`._ (_) _ \\ .' | '._) (_) | \\ _.')\\ .----..---. / |(_.' | / .-\\-. \\ | \\ 0| | ( O| O) | o| | _ | .--.____.'._.-. | \\ (_) | o -` .-` | | \\ |`-._ _ _ _ _\\ / \\ | | `. |_||_| | | o | \\_ \\ | -. .-. |.-. \\ `--..-' O | `.`-' .' _.' .' | `-.-' /-.__ ' .-' .' `-.` '.|='=.='=.='=.='=|._/_ `-'.' `-._ `. |________/\\_____| `-.' .' ).| '=' '='\\/ '=' | `._.` '---------------' //___\\ //___\\ || || LGB ||_.-. ||_.-. (_.--__) (_.--__)''') *** Remote Interpreter Reinitialized *** >>> .--..--..--..--..--..--. .' \ (`._ (_) _ \ .' | '._) (_) | \ _.')\ .----..---. / |(_.' | / .-\-. \ | \ 0| | ( O| O) | o| | _ | .--.____.'._.-. | \ (_) | o -` .-` | | \ |`-._ _ _ _ _\ / \ | | `. |_||_| | | o | \_ \ | -. .-. |.-. \ `--..-' O | `.`-' .' _.' .' | `-.-' /-.__ ' .-' .' `-.` '.|='=.='=.='=.='=|._/_ `-'.' `-._ `. |________/\_____| `-.' .' ).| '=' '='\/ '=' | `._.` '---------------' //___\ //___\ || || LGB ||_.-. ||_.-. (_.--__) (_.--__) >>> -- Jim No comment From alan.gauld at btinternet.com Fri Apr 24 10:54:06 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 24 Apr 2015 09:54:06 +0100 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <20150424024619.GT5663@ando.pearwood.info> References: <553901D6.90006@davea.name> <55398165.3050401@btinternet.com> <20150424024619.GT5663@ando.pearwood.info> Message-ID: On 24/04/15 03:46, Steven D'Aprano wrote: >> Early text encodings all worked in a single byte >> which is limited to 256 patterns. > > Oh it's much more complicated than that! Note I said *in* a single byte, ie they were all 8 bits or less. > *seven bits*, not even a full byte. It was seven bits so that there was > an extra bit available for error correction when sending over telex or > some such thing. Telex actually uses (its still in active use) its own alphabet (ITA-2) which was a 5 bit pattern based on the old Murray code. This meant there were 32 patterns, not enough for letters and numbers or other symbols so there were two sets of meanings to each pattern and a shift pattern to switch between them (which is why we have SHIFT keys on modern keyboards). Even so, lower-case letters were considered a luxury and didn't exist! It also had separate characters for line-feed and carriage-return. The keys for these were arranged vertically above each other about where the Enter key on the number keypad is today. The operator did a newline by stroking down over both keys sequentially. That's why the enter key is long and thin today.(although I don't know why the plus is that shape!) - I learned to type on a Telex machine! :-) > (There were other encodings older than ASCII, like EBCDIC, which was > used on IBM mainframes and is either 7 or 8 bits.) EBCDIC and ASCII both debuted in 1963. EBCDIC is 8 bit but has terrible sorting semantics. (I briefly programmed on OS/390 for the millenium bug panic :-( ) >> Now the simple thing to do would be just have one enormous character >> set that covers everything. That's Unicode 32 bit encoding. > > No it isn't :-) OK, I tried to simplify and confused the coding with the character set. You are of course correct! :-) > Historically, the UCS started at 16 bits, it may have reserved the full > 32 bits, but it is now guaranteed to use no more than 21 bits U+10FFFF > will be the highest code point forever. Ah, this is new to me. I assumed they could use the full 32 bits. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Fri Apr 24 12:08:00 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 24 Apr 2015 20:08:00 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> Message-ID: <20150424100800.GV5663@ando.pearwood.info> The quoting seems to be all mangled here, so please excuse me if I misattribute quotes to the wrong person: On Thu, Apr 23, 2015 at 04:15:39PM -0700, Jim Mooney wrote: > So is there any way to sniff the encoding, including the BOM (which appears > to be used or not used randomly for utf-8), so you can then use the proper > encoding, or do you wander in the wilderness? > > Pretty much guesswork. There is no foolproof way to guess encodings, since you might happen to have text which *looks* like it starts with a BOM but is actually not. E.g. if you happen to have text which starts with ?? then it might be identified as a BOM even though the author intended it to actually be ?? in the Latin-1 encoding. This is no different from any other file format. All files are made from bytes, and there is no such thing as "JPEG bytes" and "TXT bytes" and "MP3 bytes", they're all the same bytes. In principle, you could have a file which was a valid JPG, ZIP and WAV file *at the same time* (although not likely by chance). And if not those specific three, then pick some other combination. *But*, while it is true that in principle you cannot guess the encoding of files, in practice you often can guess quite successfully. Checking for a BOM is easy. For example, you could use these two functions: def guess_encoding_from_bom(filename, default='undefined'): with open(filename, 'rb') as f: sig = f.read(4) return bom2enc(sig, default) # Untested. def bom2enc(bom, default=None): if bom.startswith((b'\x00\x00\xFE\xFF', b'\xFF\xFE\x00\x00')): return 'utf_32' elif bom.startswith((b'\xFE\xFF', b'\xFF\xFE')): return 'utf_16' elif bom.startswith(b'\xEF\xBB\xBF'): return 'utf_8_sig' elif bom.startswith(b'\x2B\x2F\x76'): if len(bom) == 4 and bom[4] in b'\x2B\x2F\x38\x39': return 'utf_7' elif bom.startswith(b'\xF7\x64\x4C'): return 'utf_1' elif default is None: raise ValueError else: return default If you have a BOM, chances are very good that the text is encoded correctly. If not, you can try decoding, and if it fails, try again: for encoding in ('utf-8', 'utf-16le', 'utf-16be'): try: with open("filename", "r", encoding=encoding) as f: return f.read() except UnicodeDecodingError: pass raise UnicodeDecodingError("I give up!") You can use chardet to guess the encoding. That's a Python port of the algorithm used by Firefox to guess the encoding of webpages when the declaration is missing: https://pypi.python.org/pypi/chardet chardet works by statistically analysing the characters in the text and tries to pick an encoding that minimizes the number of gremlins. Or you can try fixing errors after they occur: http://blog.luminoso.com/2012/08/20/fix-unicode-mistakes-with-python/ > This all sounds suspiciously like the old browser wars I suffered while > webmastering. I'd almost think Microsoft had a hand in it ;') Ha! In a way they did, because Microsoft Windows code pages are legacy encodings. But given that there were no alternatives back in the 1980s, I can't blame Microsoft for the mess in the past. (Besides, MS are one of the major sponsors of Unicode, so they are helping to fix the problem too.) > If utf-8 can > handle a million characters, why isn't it just the standard? I doubt we'd > need more unless the Martians land. UTF-8 is an encoding, not a character set. The character set tells us what characters we can use: D ? ? ? ? ? ? ? ? ? ? ? are all legal in Unicode, but not in ASCII, Latin-1, ISO-8859-7, BIG-5, or any of the dozens of other character sets. The encoding tells us how to turn a character like A or ? into one or more bytes to be stored on disk, or transmitted over a network. In the non-Unicode legacy encodings, we often equate the character set with the encoding (or codec), e.g. we say that ASCII A *is* byte 65 (decimal) or 41 (hex). But that's sloppy language. The ASCII character set includes the character A (but not ?) while the encoding tells us character A gets stored as byte 41 (hex). To the best of my knowledge, Unicode is the first character set which allows for more than one encoding. Anyway, Unicode is *the* single most common character set these days, more common than even ASCII and Latin-1. About 85% of webpages use UTF-8. > Since I am reading opinions that the BOM doesn't even belong in utf-8, can > I assume just using utf-8-sig as my default encoding, even on a non-BOM > file, would do no harm? Apparently so. It looks like utf_8-sig just ignores the sig if it is present, and uses UTF-8 whether the signature is present or not. That surprises me. -- Steve From timomlists at gmail.com Fri Apr 24 12:21:32 2015 From: timomlists at gmail.com (Timo) Date: Fri, 24 Apr 2015 12:21:32 +0200 Subject: [Tutor] Spongebob Pythonpants In-Reply-To: References: Message-ID: <553A192C.7050402@gmail.com> Op 24-04-15 om 04:37 schreef Jim Mooney: > I was depressed at the thought of learning unicode, then discovered Python > was fun again since I can easily print any ascii art from > http://www.chris.com/ascii/ with a multiline print, so long as I replace > any backslash with two of them. You can save yourself some time and use a raw string: print(r""" """) Timo > Spongebob Squarepants was, of course, the > obvious first choice. The heck with Tkinter. (Bob is coming out a bit thin > in my gmail but looks fine in the REPL.) > > print(''' > .--..--..--..--..--..--. > .' \\ (`._ (_) _ \\ > .' | '._) (_) | > \\ _.')\\ .----..---. / > |(_.' | / .-\\-. \\ | > \\ 0| | ( O| O) | o| > | _ | .--.____.'._.-. | > \\ (_) | o -` .-` | > | \\ |`-._ _ _ _ _\\ / > \\ | | `. |_||_| | > | o | \\_ \\ | -. .-. > |.-. \\ `--..-' O | `.`-' .' > _.' .' | `-.-' /-.__ ' .-' > .' `-.` '.|='=.='=.='=.='=|._/_ `-'.' > `-._ `. |________/\\_____| `-.' > .' ).| '=' '='\\/ '=' | > `._.` '---------------' > //___\\ //___\\ > || || > LGB ||_.-. ||_.-. > (_.--__) (_.--__)''') > > > *** Remote Interpreter Reinitialized *** > .--..--..--..--..--..--. > .' \ (`._ (_) _ \ > .' | '._) (_) | > \ _.')\ .----..---. / > |(_.' | / .-\-. \ | > \ 0| | ( O| O) | o| > | _ | .--.____.'._.-. | > \ (_) | o -` .-` | > | \ |`-._ _ _ _ _\ / > \ | | `. |_||_| | > | o | \_ \ | -. .-. > |.-. \ `--..-' O | `.`-' .' > _.' .' | `-.-' /-.__ ' .-' > .' `-.` '.|='=.='=.='=.='=|._/_ `-'.' > `-._ `. |________/\_____| `-.' > .' ).| '=' '='\/ '=' | > `._.` '---------------' > //___\ //___\ > || || > LGB ||_.-. ||_.-. > (_.--__) (_.--__) > From alan.gauld at btinternet.com Fri Apr 24 13:24:59 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 24 Apr 2015 12:24:59 +0100 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> <55398165.3050401@btinternet.com> <20150424024619.GT5663@ando.pearwood.info> Message-ID: On 24/04/15 09:54, Alan Gauld wrote: > numbers or other symbols so there were two sets of meanings to > each pattern and a shift pattern to switch between them (which is > why we have SHIFT keys on modern keyboards). Sorry, I'm conflating two sets of issues here. The SHIFT key pre-dated teleprinters from the typewriter. The reason was the same: the physical carriage had to mechanically shift up so that the second set of characters would be printed. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Fri Apr 24 15:41:56 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 24 Apr 2015 23:41:56 +1000 Subject: [Tutor] How to close a Tkinter window from a different thread? In-Reply-To: References: Message-ID: <20150424134155.GX5663@ando.pearwood.info> Coming in late to this conversation... On Sun, Apr 19, 2015 at 10:34:43PM -0500, boB Stepp wrote: > Scenario B: > 1) I start out inside the CSA. > 2) I initiate a script in the CSA's scripting language. > 3) This script calls an external Python script in a new thread. > 4) This Python script generates a Tkinter window, populating it with > information from the CSA. > 5) Control returns to the CSA while the Tkinter window is populating > itself. The CSA's tools can be used while the Tkinter window remains > open displaying its information. I think one way of doing this is by making the Python script a daemon that runs in the background. That at least will solve the problem from Scenario A that the CSA becomes unresponsive while the Tkinter window is open: as far as the CSA is concerned, the process it launched has ended. Three follow-up problems then occur: - Can daemons run as graphical applications? - Once the daemon is running, how does the CSA communicate with it? - How do we make sure that the daemon closes down safely when the CSA quits? I don't know the answers to these. Ben Finney maintains a Python daemon library. If Ben is around, he may be able to shed some further light onto this question, and answer whether a daemon is suitable. Perhaps even give some sample code. -- Steve From robertvstepp at gmail.com Fri Apr 24 19:23:19 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 24 Apr 2015 12:23:19 -0500 Subject: [Tutor] How to close a Tkinter window from a different thread? In-Reply-To: <20150424134155.GX5663@ando.pearwood.info> References: <20150424134155.GX5663@ando.pearwood.info> Message-ID: On Fri, Apr 24, 2015 at 8:41 AM, Steven D'Aprano wrote: > On Sun, Apr 19, 2015 at 10:34:43PM -0500, boB Stepp wrote: > >> Scenario B: >> 1) I start out inside the CSA. >> 2) I initiate a script in the CSA's scripting language. >> 3) This script calls an external Python script in a new thread. >> 4) This Python script generates a Tkinter window, populating it with >> information from the CSA. >> 5) Control returns to the CSA while the Tkinter window is populating >> itself. The CSA's tools can be used while the Tkinter window remains >> open displaying its information. > > I think one way of doing this is by making the Python script a daemon > that runs in the background. That at least will solve the problem from > Scenario A that the CSA becomes unresponsive while the Tkinter window is > open: as far as the CSA is concerned, the process it launched has ended. This part sounds promising. > Three follow-up problems then occur: > > - Can daemons run as graphical applications? > > - Once the daemon is running, how does the CSA communicate with it? I'd be extremely interested if this is possible! My biggest struggles are exchanging information between the CSA and other programs external to it. And it is much harder going in one direction than the other. Liberal use of temp files seems to be the most reliable means of exchanging information, though some exploitation of the CSA's global variables is possible, though this is usually a last ditch effort when nothing else seems to work. > - How do we make sure that the daemon closes down safely when the > CSA quits? > > > I don't know the answers to these. > > Ben Finney maintains a Python daemon library. If Ben is around, he may > be able to shed some further light onto this question, and answer > whether a daemon is suitable. Perhaps even give some sample code. I'll keep my fingers crossed! -- boB From lac at openend.se Fri Apr 24 13:04:57 2015 From: lac at openend.se (Laura Creighton) Date: Fri, 24 Apr 2015 13:04:57 +0200 Subject: [Tutor] name shortening in a csv module output In-Reply-To: Message from "Steven D'Aprano" of "Fri, 24 Apr 2015 12:46:20 +1000." <20150424024619.GT5663@ando.pearwood.info> References: <553901D6.90006@davea.name> <55398165.3050401@btinternet.com><20150424024619.GT5663@ando.pearwood.info> Message-ID: <201504241104.t3OB4vvt017540@fido.openend.se> In a message of Fri, 24 Apr 2015 12:46:20 +1000, "Steven D'Aprano" writes: >The Japanese, Chinese and Korean >governments, as well as linguists, are all in agreement that despite a >few minor differences, the three languages share a common character set. I don't think that is quite the way to say it. There are characters, which look exactly the same in all three languages, and the linguists are mostly in agreement that the reason they look the same is that the are the same. But it is more usual to write Korean, these days, not with Chinese characters, (hanja) but with hangul. In the 15th century, the King, Sejong the great decided that Koreans needed a phoenetic alphabet, and made one. It doesn't look anything like chinese. And it is a phonetic, alphabetic langauge, not a stroke-and-character one. Due to the fact that the aristocracy liked using the hanja as they always had, it only really caught on in the 20th century. So if you deal with older historical Korean documents, knowing hanja will be essential to you. But if you just need modern Korean, you won't, because these days, South Koreans write their language with hangul, and a few Chinese characters tossed in on rare occasion, while I am told that in North Korean they don't use any Chinese characters at all. for the unicode aspects, see: http://en.wikipedia.org/wiki/Korean_language_and_computers Laura From robertvstepp at gmail.com Fri Apr 24 21:09:45 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 24 Apr 2015 14:09:45 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. Message-ID: I have just started reading "Test-Driven Development by Example" by Kent Beck during my lunch breaks at work. This book was a suggestion by Danny Yoo in another thread. So far it has been good reading. My current programming work flow is to add a little bit of code, run a *manual* test(s), inspect the results, correct anything that fails, rerun my manual test(s), etc. Frequently I run the entire program to see if anything has been damaged by the work so far. So TDD feels like it would fit very well with what I already try to do *manually*. I've known for a while that I need to move towards comprehensive automated testing, and I finally feel I know enough Python that I can focus on TDD and not be constantly struggling with Python syntax issues. And I really like this idea of writing a test first, it fails, now make the test pass, repeat. My wife (A teacher.) has been after me a lot lately to write some programs to make her teaching life better. So I would like to start one of her projects using TDD from the get-go. Also, this sounds like a good time to try to implement using version control software. While setting up Vim recently, I had to install Git (In order to get Vundle going.). So now I have that to play with. And to throw more fuel onto the fire of learning, why not jump into OOP for this project as well? It's about time! Plus it will make life with Tkinter a bit better, too. The project(s) will be coded in Python 3.4 on Windows 7 64-bit on my home computer. All projects that I actually complete for my wife will be implemented in her classroom, which has quite a variety of hardware and OS platforms: lap tops and desk tops, some of which are rather old, running Windows XP, Windows 7, and Ubuntu Linux. And possibly other combos that I have not been made aware of yet. First question: What testing modules/frameworks should I start out with? Doing a quick scan of the books I have, mention is made of doctest and unittest modules in the Python standard libraries. But mention is also made of two third party modules, nose and pytest. What would be the most productive use of my learning time while entering TDD waters for the first time? And beyond automating unit tests, how is integration testing done in an automated fashion? Will I require special software for this? And then there is user interface testing... And what would be the best approach to integrating Git with these efforts? Just how often does one commit one's code to the version control system? Or do I have some GCEs (Gross Conceptual Errors) here? Can Git be set up to automatically keep track of my code as I create and edit it? And as to automated testing: I really, ..., really would like to implement it on my side projects at work. But all such programs start in a proprietary scripting environment, which can call external Python (or other languages) scripts. The resulting final program is almost always an unavoidable amount of propriety scripting language (Which I always strive to minimize the amount of.), Solaris shell commands/scripts and Python. As I have been learning more Python and implementing it at work, I have found that the most successful approach seems to be to first get all of the information I need out of the CSA (commercial software environment) upfront, save it in temp files, then call a Python script to start the heavy duty processing, do everything possible in Python, generate a "reload" script file that contains language the CSA understands, and finally run that inside the CSA. How do I go about automating the testing of something like this? And apply TDD write tests first principles? And I would like to have all of that under version control, too. But while I am allowed to write my own programs for this CSA, I am not allowed to install anything else, strange as this may sound! Since the only functional editors in these bare-bones Solaris 10 environments are some simplistic default editor that I do not know the name of and vi, I long ago gravitated to doing my actual coding on my Windows PC (Being careful to save things with Unix line endings.) and FTPing to the environments where these programs will actually run. I AM allowed to install anything I want (within reason)on my PC. So I am thinking install and use Git there? And if successful automated testing can be done with this CSA situation, how difficult is it to backtrack and add test suites to stuff already written and being used? Are there special strategies and techniques for accomplishing such a feat? And any other suggestions to best start learning all of this as well as possible? As always, many thanks in advance! -- boB From alan.gauld at btinternet.com Sat Apr 25 00:03:04 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Fri, 24 Apr 2015 23:03:04 +0100 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: On 24/04/15 20:09, boB Stepp wrote: > I have just started reading "Test-Driven Development by Example" by > Kent Beck during my lunch breaks at work. The TDD bit is another whole topic that I'll probably jump into later. For now... > allowed to install anything else, strange as this may sound! Since the > only functional editors in these bare-bones Solaris 10 environments > are some simplistic default editor that I do not know the name of and > vi, vi is a great editor, no major problems there, except it doesn't have Python syntax awareness/coloring etc. . However from memory doesn't Solaris 10 come with a CDE GUI? If so it should have a graphical editor in there someplace too. It was a reasonable coding editor in that it did block indenting, bracket matching, etc. And of course it has the original SCCS for source control. Which if there's only a few of you is adequate, and easy to work with. I used SCCS on several major projects over a 10 year period. > And if successful automated testing can be done with this CSA > situation, how difficult is it to backtrack and add test suites to > stuff already written and being used? That's the traditional way of doing testing! Its not that hard if you can figure out a test environment. but from what I recall this CSA is a GUI? That makes injecting messages/commands much harder. There are tools that can do it but you can't install them... In your case building a usable test environment may be the barrier, building the test is an evolutionary process that shouldn't be too hard. If you have a CLI interface then file redirection makes it relatively easy! If you can interact with its database then stored procedures might provide away in. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From lac at openend.se Fri Apr 24 22:00:24 2015 From: lac at openend.se (Laura Creighton) Date: Fri, 24 Apr 2015 22:00:24 +0200 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: Message from boB Stepp of "Fri, 24 Apr 2015 14:09:45 -0500." References: Message-ID: <201504242000.t3OK0OoB001036@fido.openend.se> In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: >First question: What testing modules/frameworks should I start out >with? Doing a quick scan of the books I have, mention is made of >doctest and unittest modules in the Python standard libraries. But >mention is also made of two third party modules, nose and pytest. What >would be the most productive use of my learning time while entering >TDD waters for the first time? And beyond automating unit tests, how >is integration testing done in an automated fashion? Will I require >special software for this? And then there is user interface testing... You need the testing-in-python mailing list. Come on over ... http://lists.idyll.org/listinfo/testing-in-python You will find lots of familiar faces (email addresses) from this list there. Nose and py.test are very similar. I happen to like them better than unittest, but if you cannot install software on your solaris machines, you may be better off with unittest which comes with Python, which I assume you do have on your Solaris boxes. >And what would be the best approach to integrating Git with these >efforts? Just how often does one commit one's code to the version >control system? Or do I have some GCEs (Gross Conceptual Errors) here? >Can Git be set up to automatically keep track of my code as I create >and edit it? Depending on what you mean by that, the answer is 'no' or 'that is exactly what git does, there is no way to _prevent_ this'. You have to tell git when you would like to save your work. It doesn't work like autosaving in an editor -- hah hah, she has typed 300 chars now, (or it has been 5 minutes now) time to autosave -- if you never tell git to save the work, it will never get saved. So what you typically do is write a test, tell git to save it, run the test, have it fail, write some more code and run all the tests again, have them pass, tell git to save it, write another test ... If in the 'write some more code' part, you get the itch 'it would be really bad if my laptop died and I lost all this work' you tell git to save immediately and keep on going. There is a whole other layer about 'how to share your code with other people, politely, when several of you are working on the same project at one time, but if you are a one man team, you won't have to worry about that for a while. >And as to automated testing: I really, ..., really would like to >implement it on my side projects at work. But all such programs start >in a proprietary scripting environment, which can call external Python >(or other languages) scripts. The resulting final program is almost >always an unavoidable amount of propriety scripting language (Which I >always strive to minimize the amount of.), Solaris shell >commands/scripts and Python. As I have been learning more Python and >implementing it at work, I have found that the most successful >approach seems to be to first get all of the information I need out of >the CSA (commercial software environment) upfront, save it in temp >files, then call a Python script to start the heavy duty processing, >do everything possible in Python, generate a "reload" script file that >contains language the CSA understands, and finally run that inside the >CSA. How do I go about automating the testing of something like this? >And apply TDD write tests first principles? You need the testing-in-python mailing list. Whatever proprietary thing you have to integrate with, chances are somebody there has been there, and done that already and has code you would be welcome to use. >And I would like to have all of that under version control, too. But >while I am allowed to write my own programs for this CSA, I am not >allowed to install anything else, strange as this may sound! Since the >only functional editors in these bare-bones Solaris 10 environments >are some simplistic default editor that I do not know the name of and >vi, I long ago gravitated to doing my actual coding on my Windows PC >(Being careful to save things with Unix line endings.) and FTPing to >the environments where these programs will actually run. I AM allowed >to install anything I want (within reason)on my PC. So I am thinking >install and use Git there? Are you absolutely certain that you cannot install git on your bare-bones Solaris 10 environments? Or plug in a memory stick and run code from there? Because it would make your life so much easier ... > >And if successful automated testing can be done with this CSA >situation, how difficult is it to backtrack and add test suites to >stuff already written and being used? Are there special strategies and >techniques for accomplishing such a feat? Lots and lots. >And any other suggestions to best start learning all of this as well >as possible? > >As always, many thanks in advance! > > >-- >boB Laura From robertvstepp at gmail.com Sat Apr 25 00:52:50 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 24 Apr 2015 17:52:50 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: On Fri, Apr 24, 2015 at 5:03 PM, Alan Gauld wrote: > On 24/04/15 20:09, boB Stepp wrote: >> >> allowed to install anything else, strange as this may sound! Since the >> only functional editors in these bare-bones Solaris 10 environments >> are some simplistic default editor that I do not know the name of and >> vi, > > > vi is a great editor, no major problems there, except it > doesn't have Python syntax awareness/coloring etc. I am quite happy with vi! I did not mean to imply otherwise. However, as you know I have only very recently started using Vim at home and don't consider myself productive in it yet. My game plan, is once I do, to start doing my editing at work directly in Solaris 10 on vi. > However from memory doesn't Solaris 10 come with a CDE GUI? > If so it should have a graphical editor in there someplace too. > It was a reasonable coding editor in that it did block indenting, > bracket matching, etc. Your memory is indeed correct as to CDE. It has a default graphical editor, the one I referred to as "simplistic", but if it has those features I have missed them. When I say "default", it is this editor that will pop up if I open a file for editing. I will look through the menus and help again. Maybe I gave it short shrift too soon! That does not mean that there is not another graphical editor in there somewhere. I will poke around some more. But it seems, Alan, that whenever I look for something that is *supposed* to be there, I find basically a stub of an application that is missing required libraries, etc. The installers of the planning software deliberately do NOT install a substantial amount of what would normally be there in any *normal* installation of Solaris. I once *begged* the support people for this planning system to install the missing stuff for Emacs, but they refused. Of course, this is after I found someone who even knew what Emacs was, but that is another story... But I may have to revisit all of this. We went to "Smart Enterprise" on this software about a year ago. I managed to abscond with one of the 810X boxes, with the planning software intact. I got my administration to let me keep it as my development and testing environment, since they do value the programs I generate (Whenever I get time to work on them, which is usually rare.). I think now that as long as I stay on this box, that no one will mind if I install anything. I just need not to do so on our Smart Enterprise clinical planning environment. I actually started to explore this route about a half-year or so ago, having figured out how to get the 810X connected to the Internet, but then I got distracted since by what they really pay me to do! > And of course it has the original SCCS for source control. > Which if there's only a few of you is adequate, and easy > to work with. I used SCCS on several major projects over > a 10 year period. There is just lil ol' me. I will have to research SCCS. >> And if successful automated testing can be done with this CSA >> situation, how difficult is it to backtrack and add test suites to >> stuff already written and being used? > > > That's the traditional way of doing testing! Its not that hard > if you can figure out a test environment. but from what I recall > this CSA is a GUI? That makes injecting messages/commands much > harder. There are tools that can do it but you can't install > them... It is a GUI. If I can initiate the testing process from within the CSA with a small script in its language AND have the testing software generate appropriate files in the CSA's language, then I can see how it all would work. But it sounds like I would have to write (and test) an interface program between the two. Of course I am just starting the path to learning TDD, so that will probably be at least a little ways off... > In your case building a usable test environment may be the > barrier, building the test is an evolutionary process that > shouldn't be too hard. I guess this is what I was thinking about just above... > If you have a CLI interface then file redirection makes > it relatively easy! If you can interact with its database > then stored procedures might provide away in. I do. But I don't see where you are going with this yet as I do not know enough about how these testing enviroments, etc. work yet. -- boB From steve at pearwood.info Sat Apr 25 02:36:57 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 25 Apr 2015 10:36:57 +1000 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: <20150425003654.GB5663@ando.pearwood.info> So many questions... let's hope I don't miss any... :-) On Fri, Apr 24, 2015 at 02:09:45PM -0500, boB Stepp wrote: > First question: What testing modules/frameworks should I start out > with? Doing a quick scan of the books I have, mention is made of > doctest and unittest modules in the Python standard libraries. But > mention is also made of two third party modules, nose and pytest. Doctest is the simplest but less powerful. And besides, unless you are Tim Peters, the creator of doctest, nobody wants to read dozens and dozens of tests in a function docstring. unittest is quite easy to use, and powerful. Some people complain that it is not very Pythonic, but I've never felt that. It is also based on a standard and much-copied Java library, so there are versions of unittest for many different languages. I quite like it. I've never used nose, but from what I have seen of it, I will not like it. I understand that it extensively uses the assert statement for testing, which I believe is naughty: it is, I maintain, a misuse of assert. It's okay to use a few assert statements for quick and informal testing, but not for permanent professional testing. If nothing else, by using assert for your tests, you cannot possibly test your code when running under -O optimization. I have no opinion on pytest. > What > would be the most productive use of my learning time while entering > TDD waters for the first time? And beyond automating unit tests, how > is integration testing done in an automated fashion? Will I require > special software for this? And then there is user interface testing... The different sorts of tests are separated by purpose, not necessarily form or usage. Particularly for small projects, it may not make sense to split them into separate test runs. It's okay to mix regression tests into your unit tests, and even integration testing, if they are simple and fast enough. As for automated UI testing, that's hard unless you have a framework that is designed for that, something which can interact with the GUI controls and verify that they behave as expected. I have no idea about that. In any case, you should be able to run all the tests (be they doc tests, unit tests, regression tests, etc.) from a single command. I like to set things up so that these will work: python3 myproject/tests.py python3 -m myproject.tests If the integration tests are slow and complex, then you might have two test files, one which runs everything, and the other which runs everything but the integration tests. Run the quick tests frequently, and the slow tests less often. > And what would be the best approach to integrating Git with these > efforts? Just how often does one commit one's code to the version > control system? Or do I have some GCEs (Gross Conceptual Errors) here? > Can Git be set up to automatically keep track of my code as I create > and edit it? No, that's not how revision control works. You really don't want every time you hit save to count as a new revision. That would be ugly. Joel Spolsky has a good introduction to Mercurial (hg). Git is slightly different, but the fundamentals are more or less equivalent: http://hginit.com/ ? You can also watch Git For Ages 4 And Up: http://www.youtube.com/watch?v=1ffBJ4sVUb4 The executive summary of how I use version control: - work on bite-sized chunks of functionality - when the tests all pass, commit the work done - push changes to the master repo at least once per day The way I use version control on my own is that I have typically use a single branch. I rarely have to worry about contributions from others, so it's just my changes. Make sure that all the relevent files (source code, documentation, tests, images, etc.) are being tracked. Static files which never change, like reference materials, should not be. Starting from a point where all the tests pass, I decide to work on a new feature, or fix a bug. A feature might be something as small as "fix the documentation for this function", but *not* as big as "control remote controlled space ship" -- in other words, a bite-sized chunk of work, not a full meal. I write some tests, and write the minimal amount of code code that makes those tests pass: - write tests - save tests - write code - save code - run tests - fix bugs in tests - save tests - write some more code - save code - run tests again - write some more code - save code - run tests again etc. Once the tests pass, then I have a feature and/or bug fix, and I commit all the relevent changes to the VCS. hg automatically tracks files, git requires you to remind it every single time what files are being used, but either way, by the time I run `hg commit` or `git commit` I have a complete, and hopefully working, bite-sized chunk of code that has an obvious commit message: "fix bug in spam function" "correct spelling errors in module docs" "rename function ham to spam" "change function eggs from using a list to a dict" "move class K into its own submodule" etc. Notice that each change is small enough to encapsulate in a short description, but big enough that some of them may require multiple rounds of back-and-forth code-and-test before it works. I run the tests even after seemingly innoculous changes to comments or docstrings, especially docstrings. Edits to a docstring may break your doctests, or even your code, if you accidentally break the quoting. Then, when I am feeling satisfied that I've done a sufficiently large amount of work, I then push those changes to the master repo (if any). This allows me to work from various computers and still share the same code base. "Sufficiently large" may mean a single change, or a full day's work, or a whole lot of related changes that add up to one big change, whatever you prefer. But it shouldn't be less than once per day. > And as to automated testing: I really, ..., really would like to > implement it on my side projects at work. But all such programs start > in a proprietary scripting environment, which can call external Python > (or other languages) scripts. The resulting final program is almost > always an unavoidable amount of propriety scripting language (Which I > always strive to minimize the amount of.), Solaris shell > commands/scripts and Python. As I have been learning more Python and > implementing it at work, I have found that the most successful > approach seems to be to first get all of the information I need out of > the CSA (commercial software environment) upfront, save it in temp > files, then call a Python script to start the heavy duty processing, > do everything possible in Python, generate a "reload" script file that > contains language the CSA understands, and finally run that inside the > CSA. How do I go about automating the testing of something like this? > And apply TDD write tests first principles? TDD principles apply to any programming language. So long as the language that you use to write the tests has ways of calling your shell scripts and CSA code, and seeing what results they get, you can test them. For example, I might write a test which calls a shell script using os.system, and checks that the return result is 0 (success). And a second test that confirms that the shell script actually generates the file that it is supposed to. A third test to confirm that it cleans up after itself. Etc. > And I would like to have all of that under version control, too. But > while I am allowed to write my own programs for this CSA, I am not > allowed to install anything else, strange as this may sound! Since the > only functional editors in these bare-bones Solaris 10 environments > are some simplistic default editor that I do not know the name of and > vi, I long ago gravitated to doing my actual coding on my Windows PC > (Being careful to save things with Unix line endings.) and FTPing to > the environments where these programs will actually run. I AM allowed > to install anything I want (within reason)on my PC. So I am thinking > install and use Git there? Yes. > And if successful automated testing can be done with this CSA > situation, how difficult is it to backtrack and add test suites to > stuff already written and being used? Are there special strategies and > techniques for accomplishing such a feat? It's easy, especially for doc and unit tests, which is why I personally don't care too much about actually writing the tests first. For me, at least, it doesn't matter which gets written first. However, I *religiously* write the documentation first. If I don't document what the function does, how will I know what the code should do or when I am finished? -- Steve From cybervigilante at gmail.com Sat Apr 25 01:03:37 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 16:03:37 -0700 Subject: [Tutor] Spongebob Pythonpants In-Reply-To: <553A192C.7050402@gmail.com> References: <553A192C.7050402@gmail.com> Message-ID: You can save yourself some time and use a raw string: > print(r""" """) > > Timo > > Good point. I'll go to site-packages and change that. I import Bob to cheer myself up as I look at Unicode, which is like forcing a kid to go to Sunday school on a bright Summer day, instead of playing with Python. I wonder if there's a Unicode for Idiots book ;') Jim From alan.gauld at btinternet.com Sat Apr 25 02:46:18 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 25 Apr 2015 01:46:18 +0100 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: On 24/04/15 23:52, boB Stepp wrote: > There is just lil ol' me. I will have to research SCCS. SCCS is great for a single, small team. It's marginally more complex than more modern tools and it only works sensibly with text files (binaries are just uuencoded which is pretty pointless!). Basic usage is very simple: 1) create an SCCS directory in your project space - or you wind up with version files all over the place! 2) use the admin -i command to tell sccs to manage a file 3) use get to get a read only copy or get -e to get an editable one. (use -r to get a specific version) 4) use delta to save changes (it prompts you for change comments etc) There are a bunch of other reporting and searching and admin commands, but the above is all you need 90% of the time. More modern versioning systems are better but SCCS should already be installed on Solaris 10 if you have the development tools installed, which I'm guessing you do or pretty much nothing code-wise would work. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cybervigilante at gmail.com Sat Apr 25 01:34:19 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 16:34:19 -0700 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <20150424100800.GV5663@ando.pearwood.info> References: <553901D6.90006@davea.name> <20150424100800.GV5663@ando.pearwood.info> Message-ID: > > Apparently so. It looks like utf_8-sig just ignores the sig if it is > present, and uses UTF-8 whether the signature is present or not. > > That surprises me. > > -- > Steve > ____________ > I was looking things up and although there are aliases for utf_8 (utf8 and utf-8) I see no aliases for utf_8_sig, so I'm surprised the utf-8-sig I tried using, worked at all. Actually, I was trying to find the file where the aliases are so I could change it and have utf_8_sig called up when I used utf8, but it appears to be hard-coded. -- Jim From cybervigilante at gmail.com Sat Apr 25 01:43:35 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 16:43:35 -0700 Subject: [Tutor] sig no matter what Message-ID: It looks like sig works for any dash, underline combination, and is ignored if there is no BOM: >>> farf = bytes('many moons ago I sat on a rock', encoding='utf8') >>> farf b'many moons ago I sat on a rock' >>> str(farf, encoding="utf_8_sig") 'many moons ago I sat on a rock' >>> str(farf, encoding="utf-8-sig") 'many moons ago I sat on a rock' >>> str(farf, encoding="utf_8-sig") 'many moons ago I sat on a rock' >>> str(farf, encoding="utf-8_sig") 'many moons ago I sat on a rock' -- Jim Then: "Get rich flipping houses, with No Money Down!" Now: "Get rich making the next great app, with No Programming!" There's always a sucker for get-rich-quick schemes. From cybervigilante at gmail.com Sat Apr 25 02:19:33 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 17:19:33 -0700 Subject: [Tutor] Making an alias Message-ID: Actually,. I found the aliases in Lib/encodings/aliases.py and added an alias: >>> deco = bytes("I sure hate apples.", encoding='ubom') >>> deco b'\xef\xbb\xbfI sure hate apples.' >>> Tricky, though - if you don't put a comma at the end of your alias, it breaks Python (or my Pyscripter editor, anyway ;') -- Jim From steve at pearwood.info Sat Apr 25 02:50:30 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 25 Apr 2015 10:50:30 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> <20150424100800.GV5663@ando.pearwood.info> Message-ID: <20150425005029.GD5663@ando.pearwood.info> On Fri, Apr 24, 2015 at 04:34:19PM -0700, Jim Mooney wrote: > I was looking things up and although there are aliases for utf_8 (utf8 and > utf-8) I see no aliases for utf_8_sig, so I'm surprised the utf-8-sig I > tried using, worked at all. Actually, I was trying to find the file where > the aliases are so I could change it and have utf_8_sig called up when I > used utf8, but it appears to be hard-coded. I believe that Python's codecs system automatically normalises the encoding name by removing spaces, dashes and underscores, but I'm afraid that either I don't understand how it works or it is buggy: py> 'Hello'.encode('utf___---___ -- ___8') # Works. b'Hello' py> 'Hello'.encode('ut-f8') # Fails. Traceback (most recent call last): File "", line 1, in LookupError: unknown encoding: ut-f8 -- Steve From breamoreboy at yahoo.co.uk Sat Apr 25 02:52:38 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Sat, 25 Apr 2015 01:52:38 +0100 Subject: [Tutor] Spongebob Pythonpants In-Reply-To: References: <553A192C.7050402@gmail.com> Message-ID: On 25/04/2015 00:03, Jim Mooney wrote: > You can save yourself some time and use a raw string: > >> print(r""" """) >> >> Timo >> >> Good point. I'll go to site-packages and change that. I import Bob to > cheer myself up as I look at Unicode, which is like forcing a kid to go to > Sunday school on a bright Summer day, instead of playing with Python. I > wonder if there's a Unicode for Idiots book ;') > > Jim Unicode for Idiots indeed, a Python list can always find something better than that :) http://www.joelonsoftware.com/articles/Unicode.html http://nedbatchelder.com/text/unipain.html -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From davea at davea.name Sat Apr 25 02:53:30 2015 From: davea at davea.name (Dave Angel) Date: Fri, 24 Apr 2015 20:53:30 -0400 Subject: [Tutor] name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> <20150424100800.GV5663@ando.pearwood.info> Message-ID: <553AE58A.4020205@davea.name> On 04/24/2015 07:34 PM, Jim Mooney wrote: >> >> Apparently so. It looks like utf_8-sig just ignores the sig if it is >> present, and uses UTF-8 whether the signature is present or not. >> >> That surprises me. >> >> -- >> Steve >> ____________ >> > > I was looking things up and although there are aliases for utf_8 (utf8 and > utf-8) I see no aliases for utf_8_sig, so I'm surprised the utf-8-sig I > tried using, worked at all. Actually, I was trying to find the file where > the aliases are so I could change it and have utf_8_sig called up when I > used utf8, but it appears to be hard-coded. > I wouldn't use utf-8-sig for output, however, as it puts the BOM in the file for others to trip over. -- DaveA From robertvstepp at gmail.com Sat Apr 25 03:24:38 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 24 Apr 2015 20:24:38 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: <201504242000.t3OK0OoB001036@fido.openend.se> References: <201504242000.t3OK0OoB001036@fido.openend.se> Message-ID: On Fri, Apr 24, 2015 at 3:00 PM, Laura Creighton wrote: > In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: > You need the testing-in-python mailing list. Come on over ... > http://lists.idyll.org/listinfo/testing-in-python > You will find lots of familiar faces (email addresses) from this > list there. Nose and py.test are very similar. I happen to like > them better than unittest, but if you cannot install software on > your solaris machines, you may be better off with unittest which > comes with Python, which I assume you do have on your Solaris boxes. I have joined! The Python versions at work are 2.4.4 and 2.6.4(?)(Not certain about the last digit there.) Based on responses to date, the fact that unittest is in the standard library and that because of this most of my books have something about unittest, I will probably start there. I imagine that everything I learn with unittest will transfer over to other testing frameworks. >>And as to automated testing: I really, ..., really would like to >>implement it on my side projects at work. But all such programs start >>in a proprietary scripting environment, which can call external Python >>(or other languages) scripts. The resulting final program is almost >>always an unavoidable amount of propriety scripting language (Which I >>always strive to minimize the amount of.), Solaris shell >>commands/scripts and Python. As I have been learning more Python and >>implementing it at work, I have found that the most successful >>approach seems to be to first get all of the information I need out of >>the CSA (commercial software environment) upfront, save it in temp >>files, then call a Python script to start the heavy duty processing, >>do everything possible in Python, generate a "reload" script file that >>contains language the CSA understands, and finally run that inside the >>CSA. How do I go about automating the testing of something like this? >>And apply TDD write tests first principles? > > You need the testing-in-python mailing list. Whatever proprietary > thing you have to integrate with, chances are somebody there has > been there, and done that already and has code you would be > welcome to use. When I get farther along, I will probably have some very specific questions on this that I will post there. Steven and Alan have given me some very good feedback already! But if someone has already solved my problem, or, something very similar, then that will be great! >>And I would like to have all of that under version control, too. But >>while I am allowed to write my own programs for this CSA, I am not >>allowed to install anything else, strange as this may sound! Since the >>only functional editors in these bare-bones Solaris 10 environments >>are some simplistic default editor that I do not know the name of and >>vi, I long ago gravitated to doing my actual coding on my Windows PC >>(Being careful to save things with Unix line endings.) and FTPing to >>the environments where these programs will actually run. I AM allowed >>to install anything I want (within reason)on my PC. So I am thinking >>install and use Git there? > > Are you absolutely certain that you cannot install git on your bare-bones > Solaris 10 environments? Or plug in a memory stick and run code from > there? Because it would make your life so much easier ... I think that I can get an exception here (See a post in response that I made earlier today.). What I am *certain* of, is that I cannot install anything on our clinical planning environment. The Solaris workstation that I now have all to myself--I'm thinking they will now let me do what I want with it. But I must double check... But anything I develop there *should* work in the clinical environment. The planning software is the same though that may change soon as there are plans to go up a version and they may not want to do that on my testing/development machine. Thanks! -- boB From eryksun at gmail.com Sat Apr 25 04:24:55 2015 From: eryksun at gmail.com (eryksun) Date: Fri, 24 Apr 2015 21:24:55 -0500 Subject: [Tutor] sig no matter what In-Reply-To: References: Message-ID: On Fri, Apr 24, 2015 at 6:43 PM, Jim Mooney wrote: > It looks like sig works for any dash, underline combination, and is ignored > if there is no BOM: See 7.2.3 (aliases) and 7.2.7 (utf_8_sig) in the codecs documentation. https://docs.python.org/3/library/codecs.html From robertvstepp at gmail.com Sat Apr 25 05:15:20 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 24 Apr 2015 22:15:20 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: <201504242000.t3OK0OoB001036@fido.openend.se> References: <201504242000.t3OK0OoB001036@fido.openend.se> Message-ID: I saw something on Python-List that I think is worth getting on this list as Mark gave a very good reference... >Mark Lawrence wrote on Python-List: >>On 25/04/2015 01:51, Terry Reedy wrote: >>Based on my experience reading newbie posts on python list and >>Stackoverflow, learning to write real functions, without input and >>print, and repeatable tests, is the most important thing many people are >>not learning from programming books and classes. >Got to start them off somewhere so http://nedbatchelder.com/text/test0.html It is a talk that Ned Batchelder gave at PyCon 2014 called, "Getting Started Testing". You can watch the actual video (Which I just did.), go through the slides or read the slides with the video comments transcribed in. After watching the video, I feel I have a much greater understanding of testing and Python's tools to support it than I did a few minutes ago. I highly recommend watching this video -- Mr. Batchelder is a very good speaker and presents his material very effectively. Many thanks, Mark, for this link! boB From __peter__ at web.de Sat Apr 25 10:21:11 2015 From: __peter__ at web.de (Peter Otten) Date: Sat, 25 Apr 2015 10:21:11 +0200 Subject: [Tutor] Codec lookup, was Re: name shortening in a csv module output References: <553901D6.90006@davea.name> <20150424100800.GV5663@ando.pearwood.info> <20150425005029.GD5663@ando.pearwood.info> Message-ID: Steven D'Aprano wrote: > On Fri, Apr 24, 2015 at 04:34:19PM -0700, Jim Mooney wrote: > >> I was looking things up and although there are aliases for utf_8 (utf8 >> and utf-8) I see no aliases for utf_8_sig, so I'm surprised the utf-8-sig >> I tried using, worked at all. Actually, I was trying to find the file >> where the aliases are so I could change it and have utf_8_sig called up >> when I used utf8, but it appears to be hard-coded. > > I believe that Python's codecs system automatically normalises the > encoding name by removing spaces, dashes and underscores, but I'm afraid > that either I don't understand how it works or it is buggy: > > py> 'Hello'.encode('utf___---___ -- ___8') # Works. > b'Hello' > > py> 'Hello'.encode('ut-f8') # Fails. > Traceback (most recent call last): > File "", line 1, in > LookupError: unknown encoding: ut-f8 I don't think this is a bug. Normalization of the name converts to lowercase and collapses arbitrary sequences of punctuation into a single "_". The lookup that follows maps "utf8" to "utf_8" via a table: >>> [n for n, v in encodings.aliases.aliases.items() if v == "utf_8"] ['utf8_ucs2', 'utf8', 'u8', 'utf', 'utf8_ucs4'] Hm, who the heck uses "u8"? I'd rather go with >>> encodings.aliases.aliases["steven_s_preferred_encoding"] = "utf_8" >>> "Hello".encode("--- Steven's preferred encoding ---") b'Hello' ;) From alan.gauld at btinternet.com Sat Apr 25 10:21:37 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 25 Apr 2015 09:21:37 +0100 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: Having looked at this thread and its early responses I think it would be good to break it up into its two natural parts. TDD and version control are pretty much separate concepts and should be on separate threads. Bob, could you please ask your version control questions again, taking account of early responses, on a new thread? That way we can keep the TDD stuff together and the version control stuff in a separate place. In particular the version control discussion will almost certainly not be Python specific and generic to any kind of programming - which makes it only marginally on-topic for the tutor list. Thanks, -- Alan G List moderator From cybervigilante at gmail.com Sat Apr 25 03:23:50 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 18:23:50 -0700 Subject: [Tutor] Spongebob Pythonpants In-Reply-To: References: <553A192C.7050402@gmail.com> Message-ID: Unicode for Idiots indeed, a Python list can always find something better than that :) > > http://www.joelonsoftware.com/articles/Unicode.html > http://nedbatchelder.com/text/unipain.html > > > Mark Lawrence > > Batcheder's looks good. I'm going through it. I tried the Unicode Consortium website at unicode.org, but forget that - I'd rather pull my own teeth than wade through it ;') Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From cybervigilante at gmail.com Sat Apr 25 03:43:16 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 18:43:16 -0700 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <553AE58A.4020205@davea.name> References: <553901D6.90006@davea.name> <20150424100800.GV5663@ando.pearwood.info> <553AE58A.4020205@davea.name> Message-ID: > > > I wouldn't use utf-8-sig for output, however, as it puts the BOM in the > file for others to trip over. > > -- > DaveA Yeah, I found that out when I altered the aliases.py dictionary and added 'ubom' : 'utf_8_sig' as an item. Encoding didn't work out so good, but decoding was fine ;') From cybervigilante at gmail.com Sat Apr 25 05:46:44 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Fri, 24 Apr 2015 20:46:44 -0700 Subject: [Tutor] sig no matter what In-Reply-To: References: Message-ID: > See 7.2.3 (aliases) and 7.2.7 (utf_8_sig) in the codecs documentation. > > https://docs.python.org/3/library/codecs.html > The docs don't mention that case is immaterial for aliases, when it usually matters in Python. The actual dictionary entries in aliases.py often differ in case from the docs. For instance, this works: >>> p = bytes("This sure sux", encoding="uTf32") >>> p b'\xff\xfe\x00\x00T\x00\x00\x00h\x00\x00\x00i\x00\x00\x00s\x00\x00\x00 \x00\x00\x00s\x00\x00\x00u\x00\x00\x00r\x00\x00\x00e\x00\x00\x00 \x00\x00\x00s\x00\x00\x00u\x00\x00\x00x\x00\x00\x00' >>> aliases.py # utf_8 codec 'u8' : 'utf_8', 'utf' : 'utf_8', 'utf8' : 'utf_8', 'utf8_ucs2' : 'utf_8', 'utf8_ucs4' : 'utf_8', 'ubom' : 'utf_8_sig' So of course my favorite is u8 - less typing, and ubom for decoding if I get those funny bytes ;') -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From lac at openend.se Sat Apr 25 10:20:51 2015 From: lac at openend.se (Laura Creighton) Date: Sat, 25 Apr 2015 10:20:51 +0200 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: Message from boB Stepp of "Fri, 24 Apr 2015 20:24:38 -0500." References: <201504242000.t3OK0OoB001036@fido.openend.se> Message-ID: <201504250820.t3P8KplL021923@fido.openend.se> In a message of Fri, 24 Apr 2015 20:24:38 -0500, boB Stepp writes: >I have joined! Great! Great! >The Python versions at work are 2.4.4 and 2.6.4(?)(Not certain about >the last digit there.) Based on responses to date, the fact that >unittest is in the standard library and that because of this most of >my books have something about unittest, I will probably start there. I >imagine that everything I learn with unittest will transfer over to >other testing frameworks. What is even better, should you wake up one morning and decide that you really want pytest, I written have a script that automatically converts unittests to pytest tests. It is included with the pytest distribution. >> Are you absolutely certain that you cannot install git on your bare-bones >> Solaris 10 environments? Or plug in a memory stick and run code from >> there? Because it would make your life so much easier ... > >I think that I can get an exception here (See a post in response that >I made earlier today.). What I am *certain* of, is that I cannot >install anything on our clinical planning environment. The Solaris >workstation that I now have all to myself--I'm thinking they will now >let me do what I want with it. But I must double check... But anything >I develop there *should* work in the clinical environment. The >planning software is the same though that may change soon as there are >plans to go up a version and they may not want to do that on my >testing/development machine. This thought 'if it works here, it ought to work there' is an unworthy thought for somebody who has learned to test their code. ;) You go to your new machine. You pull down your tests and your code. You run all your tests. When they pass, you don't just _think_ that the code _ought to_ run here -- you _know_ the code will run because it passes all its tests. This sort of peace of mind is better than money in the bank. And, when they don't you are saved infinite amounts of embarassment. The code blows up _now_, when you are looking for problems, rather than in the middle of showing off your code to some important, influential person, because of tiny incompatibilities between what you have at home and what you have in the field. You can overcome, but never un-make a bad first impression ... So we have got to find you a way that works to get your tests and a way to run them on your production machines. Is there a way to stick a memory stick into these machines? Can you mount a filesystem there and cd to it? Over at the university here, I teach classes for the general public -- my buddies at the university let me use their machines for free. I am teaching children who don't own a computer how to make games that run on their android cell phones -- or rather, we are all teaching each other, because I am very new to this as well. So they need a machine where they can do their development, because developing on your cell phone is painful beyond belief. Every Monday morning, and more often if they feel like it, the university admins reset every computer to it's pristine 'just out of the box' state. (well, the password file will stay, but you get the idea.) Any files you leave on the machine will be removed. This is to cut down on the rate of virus infection at the university, for the most part. So we keep all the code we care about on our memory sticks, indeed in a virtualenv on our memory sticks. Solaris has virtualenv -- I checked -- see http://www.opencsw.org/packages/CSWpy-virtualenv/ So, right now, aside from a mandate from on high that people who plug memory sticks into their computers shall be boiled in oil, or the situation where your machines don't have any external ports at all, I cannot see why this solution wouldn't work for you. See any problems with this idea I missed? Laura From steve at pearwood.info Sat Apr 25 13:27:55 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 25 Apr 2015 21:27:55 +1000 Subject: [Tutor] name shortening in a csv module output In-Reply-To: <201504241104.t3OB4vvt017540@fido.openend.se> References: <553901D6.90006@davea.name> <201504241104.t3OB4vvt017540@fido.openend.se> Message-ID: <20150425112751.GF5663@ando.pearwood.info> On Fri, Apr 24, 2015 at 01:04:57PM +0200, Laura Creighton wrote: > In a message of Fri, 24 Apr 2015 12:46:20 +1000, "Steven D'Aprano" writes: > >The Japanese, Chinese and Korean > >governments, as well as linguists, are all in agreement that despite a > >few minor differences, the three languages share a common character set. > > I don't think that is quite the way to say it. There are characters, > which look exactly the same in all three languages, and the linguists > are mostly in agreement that the reason they look the same is that the > are the same. > > But it is more usual to write Korean, these days, not with Chinese > characters, (hanja) but with hangul. In the 15th century, the King, > Sejong the great decided that Koreans needed a phoenetic alphabet, and > made one. It doesn't look anything like chinese. And it is a phonetic, > alphabetic langauge, not a stroke-and-character one. Thanks for the correction Laura, I didn't know that Korean has two separate writing systems. But I did know that Japanese has at least two, one based on Chinese characters and the other not, and that Chinese itself has traditional and simplified versions of their characters. Beyond that, it's all Greek to me :-) -- Steve From eryksun at gmail.com Sat Apr 25 14:48:06 2015 From: eryksun at gmail.com (eryksun) Date: Sat, 25 Apr 2015 07:48:06 -0500 Subject: [Tutor] sig no matter what In-Reply-To: References: Message-ID: On Fri, Apr 24, 2015 at 10:46 PM, Jim Mooney wrote: > The docs don't mention that case is immaterial for aliases, when it usually > matters in Python. Section 7.2.3: Notice that spelling alternatives that only differ in case or use a hyphen instead of an underscore are also valid aliases > So of course my favorite is u8 - less typing, and ubom for decoding if I get > those funny bytes ;') Less typing, yes, but also less self-documenting. From jon.engle at gmail.com Sat Apr 25 15:46:26 2015 From: jon.engle at gmail.com (Juanald Reagan) Date: Sat, 25 Apr 2015 09:46:26 -0400 Subject: [Tutor] whois github package Message-ID: Hello! I have a question regarding how to use/implement a package found at github. https://github.com/secynic/ipwhois I am able to run the sample code without any issues but what I don't understand is how to put all the data that is returned into an indexed list. I want to be able to pick out some of the returned data through an index. For example: from ipwhois import IPWhois obj = IPWhois(ipaddy) results = [obj.lookup()] print results [0] This returns ALL the fields not just the "asn_registry" field. I looked for documentation on github but did not see anything. Any thoughts/comments are appreciated, thanks! -- Cheers, Jon From steve at pearwood.info Sat Apr 25 16:13:39 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 00:13:39 +1000 Subject: [Tutor] whois github package In-Reply-To: References: Message-ID: <20150425141338.GG5663@ando.pearwood.info> On Sat, Apr 25, 2015 at 09:46:26AM -0400, Juanald Reagan wrote: > from ipwhois import IPWhois > > obj = IPWhois(ipaddy) > results = [obj.lookup()] > print results [0] > > This returns ALL the fields not just the "asn_registry" field. I looked for > documentation on github but did not see anything. Any thoughts/comments are > appreciated, thanks! I don't have ipwhois installed, so I'm guessing, but try this: obj = IPWhois(ipaddy) results = obj.lookup() print results.asn_registry If that doesn't work, please copy and paste the entire traceback, and then run this and show us the result: vars(results) -- Steve From robertvstepp at gmail.com Sat Apr 25 17:30:02 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 25 Apr 2015 10:30:02 -0500 Subject: [Tutor] Questions (and initial responses) on using version control [Was: Introductory questions on test-driven development and implementing Git version control.] Message-ID: N.B.: This is a manual recreation of portions of the original thread, "Introductory questions on test-driven development and implementing Git version control". The portions included here are those relevant to the version control. Where "[...]" appears, this indicates I did not include those portions of the original thread here. In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: [...] >My wife (A teacher.) has been after me a lot lately to write some >programs to make her teaching life better. So I would like to start >one of her projects using TDD from the get-go. Also, this sounds like >a good time to try to implement using version control software. While >setting up Vim recently, I had to install Git (In order to get Vundle >going.). So now I have that to play with. And to throw more fuel onto >the fire of learning, why not jump into OOP for this project as well? >It's about time! Plus it will make life with Tkinter a bit better, >too. >The project(s) will be coded in Python 3.4 on Windows 7 64-bit on my >home computer. All projects that I actually complete for my wife will >be implemented in her classroom, which has quite a variety of hardware >and OS platforms: lap tops and desk tops, some of which are rather >old, running Windows XP, Windows 7, and Ubuntu Linux. And possibly >other combos that I have not been made aware of yet. [...] >And what would be the best approach to integrating Git with these >efforts? Just how often does one commit one's code to the version >control system? Or do I have some GCEs (Gross Conceptual Errors) here? >Can Git be set up to automatically keep track of my code as I create >and edit it? [...] >And I would like to have all of that under version control, too. But >while I am allowed to write my own programs for this CSA, I am not >allowed to install anything else, strange as this may sound! Since the >only functional editors in these bare-bones Solaris 10 environments >are some simplistic default editor that I do not know the name of and >vi, I long ago gravitated to doing my actual coding on my Windows PC >(Being careful to save things with Unix line endings.) and FTPing to >the environments where these programs will actually run. I AM allowed >to install anything I want (within reason)on my PC. So I am thinking >install and use Git there? ---------------------------------------------------------------------- In a message of Fri, 24 Apr 2015 at 3:00 PM, Laura Creighton writes: >In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: [...] >>And what would be the best approach to integrating Git with these >>efforts? Just how often does one commit one's code to the version >>control system? Or do I have some GCEs (Gross Conceptual Errors) here? >>Can Git be set up to automatically keep track of my code as I create >>and edit it? >Depending on what you mean by that, the answer is 'no' or 'that is >exactly what git does, there is no way to _prevent_ this'. >You have to tell git when you would like to save your work. >It doesn't work like autosaving in an editor -- hah hah, she has typed >300 chars now, (or it has been 5 minutes now) time to autosave -- if >you never tell git to save the work, it will never get saved. >So what you typically do is write a test, tell git to save it, run the >test, have it fail, write some more code and run all the tests again, >have them pass, tell git to save it, write another test ... >If in the 'write some more code' part, you get the itch 'it would be >really bad if my laptop died and I lost all this work' you tell git to >save immediately and keep on going. >There is a whole other layer about 'how to share your code with other >people, politely, when several of you are working on the same project >at one time, but if you are a one man team, you won't have to worry >about that for a while. [...] >>And I would like to have all of that under version control, too. But >>while I am allowed to write my own programs for this CSA, I am not >>allowed to install anything else, strange as this may sound! Since the >>only functional editors in these bare-bones Solaris 10 environments >>are some simplistic default editor that I do not know the name of and >>vi, I long ago gravitated to doing my actual coding on my Windows PC >>(Being careful to save things with Unix line endings.) and FTPing to >>the environments where these programs will actually run. I AM allowed >>to install anything I want (within reason)on my PC. So I am thinking >>install and use Git there? >Are you absolutely certain that you cannot install git on your bare-bones >Solaris 10 environments? Or plug in a memory stick and run code from >there? Because it would make your life so much easier ... ---------------------------------------------------------------------- On Fri., Apr 24, 2015 at 5:03 PM Alan Gauld wrote: >On 24/04/15 20:09, boB Stepp wrote: [...] >> allowed to install anything else, strange as this may sound! Since the >> only functional editors in these bare-bones Solaris 10 environments >> are some simplistic default editor that I do not know the name of and >> vi, [...] >And of course it has the original SCCS for source control. >Which if there's only a few of you is adequate, and easy >to work with. I used SCCS on several major projects over >a 10 year period. ---------------------------------------------------------------------- On Fri, Apr 24, 2015 at 5:52 PM, boB Stepp wrote: >On Fri, Apr 24, 2015 at 5:03 PM, Alan Gauld wrote: [...] >> And of course it has the original SCCS for source control. >> Which if there's only a few of you is adequate, and easy >> to work with. I used SCCS on several major projects over >> a 10 year period. >There is just lil ol' me. I will have to research SCCS. ---------------------------------------------------------------------- On Fri, Apr 24, 2015 at 7:36 PM, Steven D'Aprano wrote: >On Fri, Apr 24, 2015 at 02:09:45PM -0500, boB Stepp wrote: [...] >> And what would be the best approach to integrating Git with these >> efforts? Just how often does one commit one's code to the version >> control system? Or do I have some GCEs (Gross Conceptual Errors) here? >> Can Git be set up to automatically keep track of my code as I create >> and edit it? >No, that's not how revision control works. You really don't want every >time you hit save to count as a new revision. That would be ugly. >Joel Spolsky has a good introduction to Mercurial (hg). Git is slightly >different, but the fundamentals are more or less equivalent: >http://hginit.com/ ? >You can also watch Git For Ages 4 And Up: >http://www.youtube.com/watch?v=1ffBJ4sVUb4 >The executive summary of how I use version control: >- work on bite-sized chunks of functionality >- when the tests all pass, commit the work done >- push changes to the master repo at least once per day >The way I use version control on my own is that I have typically use a >single branch. I rarely have to worry about contributions from others, >so it's just my changes. Make sure that all the relevent files (source >code, documentation, tests, images, etc.) are being tracked. Static >files which never change, like reference materials, should not be. >Starting from a point where all the tests pass, I decide to work on a >new feature, or fix a bug. A feature might be something as small as "fix >the documentation for this function", but *not* as big as "control >remote controlled space ship" -- in other words, a bite-sized chunk of >work, not a full meal. I write some tests, and write the minimal amount >of code code that makes those tests pass: >- write tests >- save tests >- write code >- save code >- run tests >- fix bugs in tests >- save tests >- write some more code >- save code >- run tests again >- write some more code >- save code >- run tests again >etc. Once the tests pass, then I have a feature and/or bug fix, and I >commit all the relevent changes to the VCS. hg automatically tracks >files, git requires you to remind it every single time what files are >being used, but either way, by the time I run `hg commit` or `git >commit` I have a complete, and hopefully working, bite-sized chunk of >code that has an obvious commit message: >"fix bug in spam function" >"correct spelling errors in module docs" >"rename function ham to spam" >"change function eggs from using a list to a dict" >"move class K into its own submodule" >etc. Notice that each change is small enough to encapsulate in a short >description, but big enough that some of them may require multiple >rounds of back-and-forth code-and-test before it works. >I run the tests even after seemingly innoculous changes to comments or >docstrings, especially docstrings. Edits to a docstring may break your >doctests, or even your code, if you accidentally break the quoting. >Then, when I am feeling satisfied that I've done a sufficiently large >amount of work, I then push those changes to the master repo (if any). >This allows me to work from various computers and still share the same >code base. "Sufficiently large" may mean a single change, or a full >day's work, or a whole lot of related changes that add up to one big >change, whatever you prefer. But it shouldn't be less than once per day. [...] >> And I would like to have all of that under version control, too. But >> while I am allowed to write my own programs for this CSA, I am not >> allowed to install anything else, strange as this may sound! Since the >> only functional editors in these bare-bones Solaris 10 environments >> are some simplistic default editor that I do not know the name of and >> vi, I long ago gravitated to doing my actual coding on my Windows PC >> (Being careful to save things with Unix line endings.) and FTPing to >> the environments where these programs will actually run. I AM allowed >> to install anything I want (within reason)on my PC. So I am thinking >> install and use Git there? >Yes. ---------------------------------------------------------------------- On Fri, Apr 24, 2015 at 7:46 PM, Alan Gauld wrote: >On 24/04/15 23:52, boB Stepp wrote: >> There is just lil ol' me. I will have to research SCCS. >SCCS is great for a single, small team. It's marginally more complex >than more modern tools and it only works sensibly with text files >(binaries are just uuencoded which is pretty pointless!). >Basic usage is very simple: >1) create an SCCS directory in your project space - or you wind up > with version files all over the place! >2) use the admin -i command to tell sccs to manage a file >3) use get to get a read only copy or get -e to get an editable one. > (use -r to get a specific version) >4) use delta to save changes (it prompts you for change comments etc) >There are a bunch of other reporting and searching and admin >commands, but the above is all you need 90% of the time. >More modern versioning systems are better but SCCS should already >be installed on Solaris 10 if you have the development tools >installed, which I'm guessing you do or pretty much >nothing code-wise would work. ---------------------------------------------------------------------- On Fri, Apr 24, 2015 at 8:24 PM, boB Stepp wrote: >On Fri, Apr 24, 2015 at 3:00 PM, Laura Creighton wrote: >> In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: [...] >>>And I would like to have all of that under version control, too. But >>>while I am allowed to write my own programs for this CSA, I am not >>>allowed to install anything else, strange as this may sound! Since the >>>only functional editors in these bare-bones Solaris 10 environments >>>are some simplistic default editor that I do not know the name of and >>>vi, I long ago gravitated to doing my actual coding on my Windows PC >>>(Being careful to save things with Unix line endings.) and FTPing to >>>the environments where these programs will actually run. I AM allowed >>>to install anything I want (within reason)on my PC. So I am thinking >>>install and use Git there? >> >> Are you absolutely certain that you cannot install git on your bare-bones >> Solaris 10 environments? Or plug in a memory stick and run code from >> there? Because it would make your life so much easier ... >I think that I can get an exception here (See a post in response that >I made earlier today.). What I am *certain* of, is that I cannot >install anything on our clinical planning environment. The Solaris >workstation that I now have all to myself--I'm thinking they will now >let me do what I want with it. But I must double check... But anything >I develop there *should* work in the clinical environment. The >planning software is the same though that may change soon as there are >plans to go up a version and they may not want to do that on my >testing/development machine. ---------------------------------------------------------------------- From robertvstepp at gmail.com Sat Apr 25 17:34:59 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 25 Apr 2015 10:34:59 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: On Sat, Apr 25, 2015 at 3:21 AM, Alan Gauld wrote: > Having looked at this thread and its early responses I think it > would be good to break it up into its two natural parts. TDD > and version control are pretty much separate concepts and > should be on separate threads. > > Bob, could you please ask your version control questions again, > taking account of early responses, on a new thread? That way > we can keep the TDD stuff together and the version control > stuff in a separate place. Done! I do not know if what I did matches your intent, but I hope so! I stuffed everything relevant to version control into a single email, trying my best to keep attributions, etc., accurate. It makes for a long post, but it has everything nicely in place. I just hope Gmail did not mangle anything! In retrospect, I wish I had copied and pasted every post so far into Vim, did my editing there, and re-copy and paste into a new email. I keep forgetting that text is text... -- boB From akleider at sonic.net Sat Apr 25 17:51:58 2015 From: akleider at sonic.net (Alex Kleider) Date: Sat, 25 Apr 2015 08:51:58 -0700 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: On 2015-04-25 08:34, boB Stepp wrote: > On Sat, Apr 25, 2015 at 3:21 AM, Alan Gauld > wrote: >> Having looked at this thread and its early responses I think it >> would be good to break it up into its two natural parts. TDD >> and version control are pretty much separate concepts and >> should be on separate threads. >> >> Bob, could you please ask your version control questions again, >> taking account of early responses, on a new thread? That way >> we can keep the TDD stuff together and the version control >> stuff in a separate place. > > Done! I do not know if what I did matches your intent, but I hope so! > I stuffed everything relevant to version control into a single email, > trying my best to keep attributions, etc., accurate. It makes for a > long post, but it has everything nicely in place. I just hope Gmail > did not mangle anything! > > In retrospect, I wish I had copied and pasted every post so far into > Vim, did my editing there, and re-copy and paste into a new email. I > keep forgetting that text is text... This might be of interest to you: https://addons.mozilla.org/en-us/firefox/addon/its-all-text/ From robertvstepp at gmail.com Sat Apr 25 17:58:14 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 25 Apr 2015 10:58:14 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: <201504250820.t3P8KplL021923@fido.openend.se> References: <201504242000.t3OK0OoB001036@fido.openend.se> <201504250820.t3P8KplL021923@fido.openend.se> Message-ID: On Sat, Apr 25, 2015 at 3:20 AM, Laura Creighton wrote: > In a message of Fri, 24 Apr 2015 20:24:38 -0500, boB Stepp writes: >>The Python versions at work are 2.4.4 and 2.6.4(?)(Not certain about >>the last digit there.) Based on responses to date, the fact that >>unittest is in the standard library and that because of this most of >>my books have something about unittest, I will probably start there. I >>imagine that everything I learn with unittest will transfer over to >>other testing frameworks. > > What is even better, should you wake up one morning and decide that > you really want pytest, I written have a script that automatically converts > unittests to pytest tests. It is included with the pytest distribution. This is very good to know! >>> Are you absolutely certain that you cannot install git on your bare-bones >>> Solaris 10 environments? Or plug in a memory stick and run code from >>> there? Because it would make your life so much easier ... On your original post this did not register in my brain properly. This might be possible. The thin clients that hook us to Smart Enterprise *do* have a couple of USB ports. I know that they are functional as I watched the installer using one. I will have to investigate this! >>I think that I can get an exception here (See a post in response that >>I made earlier today.). What I am *certain* of, is that I cannot >>install anything on our clinical planning environment. The Solaris >>workstation that I now have all to myself--I'm thinking they will now >>let me do what I want with it. But I must double check... But anything >>I develop there *should* work in the clinical environment. The >>planning software is the same though that may change soon as there are >>plans to go up a version and they may not want to do that on my >>testing/development machine. > > This thought 'if it works here, it ought to work there' is an unworthy > thought for somebody who has learned to test their code. ;) You go to your > new machine. You pull down your tests and your code. You run all your > tests. When they pass, you don't just _think_ that the code _ought to_ > run here -- you _know_ the code will run because it passes all its tests. You have a very gentle way of chastising me! ~(:>)) I *do* test when I transfer code to the production environment, but to date these have all been manual. And the whole point here is for me to learn how to do full-fledged automated testing. And if there is ever a place to ensure I do this, it is in the production environment! But I did not see how to make it work there. Perhaps the memory stick idea or Alan's SCCS can get around these difficulties. > So we have got to find you a way that works to get your tests and a way > to run them on your production machines. > > Is there a way to stick a memory stick into these machines? Can you > mount a filesystem there and cd to it?... As I said above, I will see if this is doable. The ports exist, but are they usable? > ...So we keep all the code we care about on our memory > sticks, indeed in a virtualenv on our memory sticks. Solaris has > virtualenv -- I checked -- see > http://www.opencsw.org/packages/CSWpy-virtualenv/ I have only messed around with a virtual environment once a few years ago for some project at home that I no longer recall the details for. I did not get very deeply into understanding things, so I would have some learning curve here. On a different testing-related note, I have read that it is a good idea sometimes to do one's code testing within the confines of a virtual environment for safety reasons, particularly if some code comes from outside sources? Would you mind speaking to that topic? > So, right now, aside from a mandate from on high that people who > plug memory sticks into their computers shall be boiled in oil, or > the situation where your machines don't have any external ports at all, > I cannot see why this solution wouldn't work for you. There might be some who would enjoy doing this! ~(:>)) IS is a bit sensitive about the use of memory sticks. We have had multiple instances of virus infections via this route, often from people who really should have known better. But I am pleased to report I have not been one of them! (Keeping fingers crossed, knocking on wood, etc.) -- boB From alan.gauld at btinternet.com Sat Apr 25 18:19:31 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 25 Apr 2015 17:19:31 +0100 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: Message-ID: On 25/04/15 16:34, boB Stepp wrote: > Done! I do not know if what I did matches your intent, but I hope so! You've done much more than I intended. I only wanted you to consider what has already been said then re-frame any remaining VC questions in a new mail. But no harm done except for your time. Thanks. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Sat Apr 25 19:40:16 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sat, 25 Apr 2015 18:40:16 +0100 Subject: [Tutor] Questions (and initial responses) on using version control [Was: Introductory questions on test-driven development and implementing Git version control.] In-Reply-To: References: Message-ID: On 25/04/15 16:30, boB Stepp wrote: >> And what would be the best approach to integrating Git with these >> efforts? Just how often does one commit one's code to the version >> control system? Or do I have some GCEs (Gross Conceptual Errors) here? Going back to first principles. What is often called Version Control or Configuration Management actually encompasses two distinct disciplines: 1) File versioning 2) Release management File versioning is where you save multiple versions of files as you go so that you can revert to a previous version. This could be because you've made some bad changes that you want to back out or it could be because you have a production version that is not current and it has developed a bug. It also supports branching which is where you develop parallel streams of development. This could be to support different platforms etc. Its also an important tool to manage multiple developers working on the same files - but that is less of an issue for you. Release management is about organising groups of files into releases and versioning the whole release. Thus release 1.0 contains: v1.4 of File A v3.7 of FileB v2.2 of Fi;le C and so on. A release should ideally also keep the toolset with which the release was created (older compiler versions/OS etc) but often that is simply stored as a text file with the necessary details recorded. That way you can call up release 1 at any time. As with files you may have branched parallel developments of releases as well as individual files. For example you may have 2 production releases, a system test release and one or more development releases active at any time. You may need to recreate any of those releases at any given moment. So, to decide what to do about Config Mgt you need to decide whether you want to focus on version control or release control? Or both. The tools tend to be focused on one or the other. If you are just starting out I'd recommend a basic version control setup because its much simpler and you can use the reporting tools and batch files to manually handle releases initially. If you do a lot of releases with multiple files then you should maybe jump into a release capable tool right away. CM tools are like editors and they tend to have rabid supporters. I've used over a dozen of them over the years, mostly commercial and many costing thousands of dollars, but there are capable open source ones nowadays that can certainly do all that you want. Many of the modern tools are focussed on multi-developer, parallel, distributed, developments; as is typical of open source projects. If you are a small team/individual working on a single release stream in a single site things are much simpler. My experience in that area is limited to SCCS/RCS for file based version control and CVS and SVN for release management. But my needs are fairly simple... Also many tools can be integrated with editors like Eclipse, Netbeans, Visual Studio, emacs and vim. This makes basic functions much easier to use - literally a mouse click away. But the first decision is what exactly do you want to use the tool for? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From cybervigilante at gmail.com Sat Apr 25 16:56:26 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 25 Apr 2015 07:56:26 -0700 Subject: [Tutor] Codec lookup, was Re: name shortening in a csv module output In-Reply-To: References: <553901D6.90006@davea.name> <20150424100800.GV5663@ando.pearwood.info> <20150425005029.GD5663@ando.pearwood.info> Message-ID: > > Hm, who the heck uses "u8"? I'd rather go with > > >>> encodings.aliases.aliases["steven_s_preferred_encoding"] = "utf_8" > >>> "Hello".encode("--- Steven's preferred encoding ---") > b'Hello' > > ;) > Peter Otten > __ > Or normalize almost any mistyping ;'): >>> encodings.normalize_encoding('utf&&$%##8') 'utf_8' -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From jon.engle at gmail.com Sat Apr 25 20:13:50 2015 From: jon.engle at gmail.com (Juanald Reagan) Date: Sat, 25 Apr 2015 14:13:50 -0400 Subject: [Tutor] Tutor Digest, Vol 134, Issue 86 In-Reply-To: References: Message-ID: Okay, so it doesn't look like that worked...here is the traceback. I don't understand the second part of your request. Jons-desktop:whois-0.7 2 jon$ python pythonwhois.py 8.8.8.8 Traceback (most recent call last): File "pythonwhois.py", line 14, in print results.asn_registry AttributeError: 'dict' object has no attribute 'asn_registry' On Sat, Apr 25, 2015 at 11:30 AM, wrote: > Send Tutor mailing list submissions to > tutor at python.org > > To subscribe or unsubscribe via the World Wide Web, visit > https://mail.python.org/mailman/listinfo/tutor > or, via email, send a message with subject or body 'help' to > tutor-request at python.org > > You can reach the person managing the list at > tutor-owner at python.org > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Tutor digest..." > > > Today's Topics: > > 1. Re: name shortening in a csv module output (Steven D'Aprano) > 2. Re: sig no matter what (eryksun) > 3. whois github package (Juanald Reagan) > 4. Re: whois github package (Steven D'Aprano) > 5. Questions (and initial responses) on using version control > [Was: Introductory questions on test-driven development and > implementing Git version control.] (boB Stepp) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Sat, 25 Apr 2015 21:27:55 +1000 > From: Steven D'Aprano > To: tutor at python.org > Subject: Re: [Tutor] name shortening in a csv module output > Message-ID: <20150425112751.GF5663 at ando.pearwood.info> > Content-Type: text/plain; charset=us-ascii > > On Fri, Apr 24, 2015 at 01:04:57PM +0200, Laura Creighton wrote: > > In a message of Fri, 24 Apr 2015 12:46:20 +1000, "Steven D'Aprano" > writes: > > >The Japanese, Chinese and Korean > > >governments, as well as linguists, are all in agreement that despite a > > >few minor differences, the three languages share a common character set. > > > > I don't think that is quite the way to say it. There are characters, > > which look exactly the same in all three languages, and the linguists > > are mostly in agreement that the reason they look the same is that the > > are the same. > > > > But it is more usual to write Korean, these days, not with Chinese > > characters, (hanja) but with hangul. In the 15th century, the King, > > Sejong the great decided that Koreans needed a phoenetic alphabet, and > > made one. It doesn't look anything like chinese. And it is a phonetic, > > alphabetic langauge, not a stroke-and-character one. > > Thanks for the correction Laura, I didn't know that Korean has two > separate writing systems. But I did know that Japanese has at least two, > one based on Chinese characters and the other not, and that Chinese > itself has traditional and simplified versions of their characters. > Beyond that, it's all Greek to me :-) > > > -- > Steve > > > ------------------------------ > > Message: 2 > Date: Sat, 25 Apr 2015 07:48:06 -0500 > From: eryksun > To: "tutor at python.org" > Subject: Re: [Tutor] sig no matter what > Message-ID: > < > CACL+1at+xGqJ0TDNy0k4jzZ7Ae4nh7NqfruvrF-QehmYTA2uxA at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > On Fri, Apr 24, 2015 at 10:46 PM, Jim Mooney > wrote: > > The docs don't mention that case is immaterial for aliases, when it > usually > > matters in Python. > > Section 7.2.3: > > Notice that spelling alternatives that only differ in case or use a > hyphen > instead of an underscore are also valid aliases > > > So of course my favorite is u8 - less typing, and ubom for decoding if I > get > > those funny bytes ;') > > Less typing, yes, but also less self-documenting. > > > ------------------------------ > > Message: 3 > Date: Sat, 25 Apr 2015 09:46:26 -0400 > From: Juanald Reagan > To: "tutor at python.org" > Subject: [Tutor] whois github package > Message-ID: > 6GU2doxq2c8kcKyb8qQ9jcPMUZT9_VU+7x8V9TTsQ at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > Hello! I have a question regarding how to use/implement a package found at > github. > > https://github.com/secynic/ipwhois > > I am able to run the sample code without any issues but what I don't > understand is how to put all the data that is returned into an indexed > list. I want to be able to pick out some of the returned data through an > index. > > For example: > > from ipwhois import IPWhois > > obj = IPWhois(ipaddy) > results = [obj.lookup()] > print results [0] > > This returns ALL the fields not just the "asn_registry" field. I looked for > documentation on github but did not see anything. Any thoughts/comments are > appreciated, thanks! > > -- > Cheers, > > Jon > > > ------------------------------ > > Message: 4 > Date: Sun, 26 Apr 2015 00:13:39 +1000 > From: Steven D'Aprano > To: tutor at python.org > Subject: Re: [Tutor] whois github package > Message-ID: <20150425141338.GG5663 at ando.pearwood.info> > Content-Type: text/plain; charset=us-ascii > > On Sat, Apr 25, 2015 at 09:46:26AM -0400, Juanald Reagan wrote: > > > from ipwhois import IPWhois > > > > obj = IPWhois(ipaddy) > > results = [obj.lookup()] > > print results [0] > > > > This returns ALL the fields not just the "asn_registry" field. I looked > for > > documentation on github but did not see anything. Any thoughts/comments > are > > appreciated, thanks! > > I don't have ipwhois installed, so I'm guessing, but try this: > > > obj = IPWhois(ipaddy) > results = obj.lookup() > print results.asn_registry > > If that doesn't work, please copy and paste the entire traceback, and > then run this and show us the result: > > vars(results) > > > > > -- > Steve > > > ------------------------------ > > Message: 5 > Date: Sat, 25 Apr 2015 10:30:02 -0500 > From: boB Stepp > To: tutor > Subject: [Tutor] Questions (and initial responses) on using version > control [Was: Introductory questions on test-driven development and > implementing Git version control.] > Message-ID: > 4diYR0A at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > N.B.: This is a manual recreation of portions of the original thread, > "Introductory questions on test-driven development and implementing > Git version control". The portions included here are those relevant to > the version control. Where "[...]" appears, this indicates I did not > include those portions of the original thread here. > > In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: > > [...] > > >My wife (A teacher.) has been after me a lot lately to write some > >programs to make her teaching life better. So I would like to start > >one of her projects using TDD from the get-go. Also, this sounds like > >a good time to try to implement using version control software. While > >setting up Vim recently, I had to install Git (In order to get Vundle > >going.). So now I have that to play with. And to throw more fuel onto > >the fire of learning, why not jump into OOP for this project as well? > >It's about time! Plus it will make life with Tkinter a bit better, > >too. > > >The project(s) will be coded in Python 3.4 on Windows 7 64-bit on my > >home computer. All projects that I actually complete for my wife will > >be implemented in her classroom, which has quite a variety of hardware > >and OS platforms: lap tops and desk tops, some of which are rather > >old, running Windows XP, Windows 7, and Ubuntu Linux. And possibly > >other combos that I have not been made aware of yet. > > [...] > > >And what would be the best approach to integrating Git with these > >efforts? Just how often does one commit one's code to the version > >control system? Or do I have some GCEs (Gross Conceptual Errors) here? > >Can Git be set up to automatically keep track of my code as I create > >and edit it? > > [...] > > >And I would like to have all of that under version control, too. But > >while I am allowed to write my own programs for this CSA, I am not > >allowed to install anything else, strange as this may sound! Since the > >only functional editors in these bare-bones Solaris 10 environments > >are some simplistic default editor that I do not know the name of and > >vi, I long ago gravitated to doing my actual coding on my Windows PC > >(Being careful to save things with Unix line endings.) and FTPing to > >the environments where these programs will actually run. I AM allowed > >to install anything I want (within reason)on my PC. So I am thinking > >install and use Git there? > ---------------------------------------------------------------------- > In a message of Fri, 24 Apr 2015 at 3:00 PM, Laura Creighton writes: > > >In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: > > [...] > > >>And what would be the best approach to integrating Git with these > >>efforts? Just how often does one commit one's code to the version > >>control system? Or do I have some GCEs (Gross Conceptual Errors) here? > >>Can Git be set up to automatically keep track of my code as I create > >>and edit it? > > >Depending on what you mean by that, the answer is 'no' or 'that is > >exactly what git does, there is no way to _prevent_ this'. > > >You have to tell git when you would like to save your work. > >It doesn't work like autosaving in an editor -- hah hah, she has typed > >300 chars now, (or it has been 5 minutes now) time to autosave -- if > >you never tell git to save the work, it will never get saved. > > >So what you typically do is write a test, tell git to save it, run the > >test, have it fail, write some more code and run all the tests again, > >have them pass, tell git to save it, write another test ... > > >If in the 'write some more code' part, you get the itch 'it would be > >really bad if my laptop died and I lost all this work' you tell git to > >save immediately and keep on going. > > >There is a whole other layer about 'how to share your code with other > >people, politely, when several of you are working on the same project > >at one time, but if you are a one man team, you won't have to worry > >about that for a while. > > [...] > > >>And I would like to have all of that under version control, too. But > >>while I am allowed to write my own programs for this CSA, I am not > >>allowed to install anything else, strange as this may sound! Since the > >>only functional editors in these bare-bones Solaris 10 environments > >>are some simplistic default editor that I do not know the name of and > >>vi, I long ago gravitated to doing my actual coding on my Windows PC > >>(Being careful to save things with Unix line endings.) and FTPing to > >>the environments where these programs will actually run. I AM allowed > >>to install anything I want (within reason)on my PC. So I am thinking > >>install and use Git there? > > >Are you absolutely certain that you cannot install git on your bare-bones > >Solaris 10 environments? Or plug in a memory stick and run code from > >there? Because it would make your life so much easier ... > ---------------------------------------------------------------------- > On Fri., Apr 24, 2015 at 5:03 PM Alan Gauld wrote: > > >On 24/04/15 20:09, boB Stepp wrote: > > [...] > > >> allowed to install anything else, strange as this may sound! Since the > >> only functional editors in these bare-bones Solaris 10 environments > >> are some simplistic default editor that I do not know the name of and > >> vi, > > [...] > > >And of course it has the original SCCS for source control. > >Which if there's only a few of you is adequate, and easy > >to work with. I used SCCS on several major projects over > >a 10 year period. > ---------------------------------------------------------------------- > On Fri, Apr 24, 2015 at 5:52 PM, boB Stepp wrote: > >On Fri, Apr 24, 2015 at 5:03 PM, Alan Gauld > wrote: > > [...] > > >> And of course it has the original SCCS for source control. > >> Which if there's only a few of you is adequate, and easy > >> to work with. I used SCCS on several major projects over > >> a 10 year period. > > >There is just lil ol' me. I will have to research SCCS. > ---------------------------------------------------------------------- > On Fri, Apr 24, 2015 at 7:36 PM, Steven D'Aprano wrote: > >On Fri, Apr 24, 2015 at 02:09:45PM -0500, boB Stepp wrote: > > [...] > > >> And what would be the best approach to integrating Git with these > >> efforts? Just how often does one commit one's code to the version > >> control system? Or do I have some GCEs (Gross Conceptual Errors) here? > >> Can Git be set up to automatically keep track of my code as I create > >> and edit it? > > >No, that's not how revision control works. You really don't want every > >time you hit save to count as a new revision. That would be ugly. > > >Joel Spolsky has a good introduction to Mercurial (hg). Git is slightly > >different, but the fundamentals are more or less equivalent: > > >http://hginit.com/ > ? > >You can also watch Git For Ages 4 And Up: > > >http://www.youtube.com/watch?v=1ffBJ4sVUb4 > > > >The executive summary of how I use version control: > > >- work on bite-sized chunks of functionality > >- when the tests all pass, commit the work done > >- push changes to the master repo at least once per day > > > >The way I use version control on my own is that I have typically use a > >single branch. I rarely have to worry about contributions from others, > >so it's just my changes. Make sure that all the relevent files (source > >code, documentation, tests, images, etc.) are being tracked. Static > >files which never change, like reference materials, should not be. > > >Starting from a point where all the tests pass, I decide to work on a > >new feature, or fix a bug. A feature might be something as small as "fix > >the documentation for this function", but *not* as big as "control > >remote controlled space ship" -- in other words, a bite-sized chunk of > >work, not a full meal. I write some tests, and write the minimal amount > >of code code that makes those tests pass: > > >- write tests > >- save tests > >- write code > >- save code > >- run tests > >- fix bugs in tests > >- save tests > >- write some more code > >- save code > >- run tests again > >- write some more code > >- save code > >- run tests again > > > >etc. Once the tests pass, then I have a feature and/or bug fix, and I > >commit all the relevent changes to the VCS. hg automatically tracks > >files, git requires you to remind it every single time what files are > >being used, but either way, by the time I run `hg commit` or `git > >commit` I have a complete, and hopefully working, bite-sized chunk of > >code that has an obvious commit message: > > >"fix bug in spam function" > >"correct spelling errors in module docs" > >"rename function ham to spam" > >"change function eggs from using a list to a dict" > >"move class K into its own submodule" > > >etc. Notice that each change is small enough to encapsulate in a short > >description, but big enough that some of them may require multiple > >rounds of back-and-forth code-and-test before it works. > > >I run the tests even after seemingly innoculous changes to comments or > >docstrings, especially docstrings. Edits to a docstring may break your > >doctests, or even your code, if you accidentally break the quoting. > > >Then, when I am feeling satisfied that I've done a sufficiently large > >amount of work, I then push those changes to the master repo (if any). > >This allows me to work from various computers and still share the same > >code base. "Sufficiently large" may mean a single change, or a full > >day's work, or a whole lot of related changes that add up to one big > >change, whatever you prefer. But it shouldn't be less than once per day. > > [...] > > >> And I would like to have all of that under version control, too. But > >> while I am allowed to write my own programs for this CSA, I am not > >> allowed to install anything else, strange as this may sound! Since the > >> only functional editors in these bare-bones Solaris 10 environments > >> are some simplistic default editor that I do not know the name of and > >> vi, I long ago gravitated to doing my actual coding on my Windows PC > >> (Being careful to save things with Unix line endings.) and FTPing to > >> the environments where these programs will actually run. I AM allowed > >> to install anything I want (within reason)on my PC. So I am thinking > >> install and use Git there? > > >Yes. > ---------------------------------------------------------------------- > On Fri, Apr 24, 2015 at 7:46 PM, Alan Gauld wrote: > >On 24/04/15 23:52, boB Stepp wrote: > > >> There is just lil ol' me. I will have to research SCCS. > > > >SCCS is great for a single, small team. It's marginally more complex > >than more modern tools and it only works sensibly with text files > >(binaries are just uuencoded which is pretty pointless!). > > >Basic usage is very simple: > >1) create an SCCS directory in your project space - or you wind up > > with version files all over the place! > >2) use the admin -i command to tell sccs to manage a file > >3) use get to get a read only copy or get -e to get an editable one. > > (use -r to get a specific version) > >4) use delta to save changes (it prompts you for change comments etc) > > >There are a bunch of other reporting and searching and admin > >commands, but the above is all you need 90% of the time. > >More modern versioning systems are better but SCCS should already > >be installed on Solaris 10 if you have the development tools > >installed, which I'm guessing you do or pretty much > >nothing code-wise would work. > ---------------------------------------------------------------------- > On Fri, Apr 24, 2015 at 8:24 PM, boB Stepp wrote: > >On Fri, Apr 24, 2015 at 3:00 PM, Laura Creighton wrote: > >> In a message of Fri, 24 Apr 2015 14:09:45 -0500, boB Stepp writes: > > [...] > > >>>And I would like to have all of that under version control, too. But > >>>while I am allowed to write my own programs for this CSA, I am not > >>>allowed to install anything else, strange as this may sound! Since the > >>>only functional editors in these bare-bones Solaris 10 environments > >>>are some simplistic default editor that I do not know the name of and > >>>vi, I long ago gravitated to doing my actual coding on my Windows PC > >>>(Being careful to save things with Unix line endings.) and FTPing to > >>>the environments where these programs will actually run. I AM allowed > >>>to install anything I want (within reason)on my PC. So I am thinking > >>>install and use Git there? > >> > >> Are you absolutely certain that you cannot install git on your > bare-bones > >> Solaris 10 environments? Or plug in a memory stick and run code from > >> there? Because it would make your life so much easier ... > > >I think that I can get an exception here (See a post in response that > >I made earlier today.). What I am *certain* of, is that I cannot > >install anything on our clinical planning environment. The Solaris > >workstation that I now have all to myself--I'm thinking they will now > >let me do what I want with it. But I must double check... But anything > >I develop there *should* work in the clinical environment. The > >planning software is the same though that may change soon as there are > >plans to go up a version and they may not want to do that on my > >testing/development machine. > ---------------------------------------------------------------------- > > > ------------------------------ > > Subject: Digest Footer > > _______________________________________________ > Tutor maillist - Tutor at python.org > https://mail.python.org/mailman/listinfo/tutor > > > ------------------------------ > > End of Tutor Digest, Vol 134, Issue 86 > ************************************** > -- Cheers, Jon S. Engle jon.engle at gmail.com From steve at pearwood.info Sun Apr 26 01:07:31 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 09:07:31 +1000 Subject: [Tutor] Python Whois [was Re: Tutor Digest, Vol 134, Issue 86] In-Reply-To: References: Message-ID: <20150425230730.GH5663@ando.pearwood.info> Hi Jon, Before I answer your question, first some mailing list housekeeping. If you are going to read and respond to messages here, please change from "Daily Digest" to individual messages. Your reply includes 500 lines (about 10 or 12 pages!) of old messages. We've already seen those messages before, we don't need to see them again. And most of them have nothing to do with your question. This is what happens when you reply to Digests. It is annoying to the reader, and for those people who pay for internet access by the byte (yes, there are still some of them) it costs them money. So please don't do it in the future. Now, back to your question: On Sat, Apr 25, 2015 at 02:13:50PM -0400, Juanald Reagan wrote: > Okay, so it doesn't look like that worked...here is the traceback. I don't > understand the second part of your request. > > Jons-desktop:whois-0.7 2 jon$ python pythonwhois.py > > 8.8.8.8 > > Traceback (most recent call last): > > File "pythonwhois.py", line 14, in > > print results.asn_registry > > AttributeError: 'dict' object has no attribute 'asn_registry' Try these three lines instead: print type(results) print results print results['asn_registry'] The first two lines are to find out what sort of object the IPWhois result is, and hopefully what its contents are. I *think* it will be a dict, in which case the last line may be the answer you are looking for: to extract the 'asn_registry' field from the dict, you will use results['asn_registry'] Assuming that works, does it answer your question? If not, can you explain what you want to do? -- Steve From alan.gauld at btinternet.com Sun Apr 26 01:25:59 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 26 Apr 2015 00:25:59 +0100 Subject: [Tutor] whois github package In-Reply-To: References: Message-ID: On 25/04/15 14:46, Juanald Reagan wrote: > Hello! I have a question regarding how to use/implement a package found at > github. > > https://github.com/secynic/ipwhois We are not experts on this here since this list s for people learning the core Python lamguage and its standard library. Howe er I see Steven has had a go at helping you. Another thing you could try is using Pythons built in help() function: After >>> from ipwhois import IPWhois Try >>> help(IPWhois) > obj = IPWhois(ipaddy) Now try >>> help(obj) >>> help(obj.lookup) That might give some clues about what methods exist and what they return. (Assuming the author included doc strings of course! > results = [obj.lookup()] > print results [0] > > This returns ALL the fields not just the "asn_registry" field. That's what I'd expect since you put the output of lookup() as the first element of the list. You then printed that element. But if you showed us even a snippet of what that actually looked like it would help us answer your question about how to access it. Remember we don't know this package so you have to show us what is happening not just summarize what you think its doing. > I looked for documentation on github Python documentation is often embedded in the module/objects help() will often reveal it. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From dyoo at hashcollision.org Sun Apr 26 01:38:15 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Sat, 25 Apr 2015 16:38:15 -0700 Subject: [Tutor] Looking up a value in a dictionary Message-ID: On Sat, Apr 25, 2015 at 11:13 AM, Juanald Reagan wrote: > Okay, so it doesn't look like that worked...here is the traceback. I don't > understand the second part of your request. > > Jons-desktop:whois-0.7 2 jon$ python pythonwhois.py > > 8.8.8.8 > > Traceback (most recent call last): > > File "pythonwhois.py", line 14, in > > print results.asn_registry > > AttributeError: 'dict' object has no attribute 'asn_registry' Because of the lack of subject-line context, I'm having a hard time following this thread. I've changed the subject to "Looking up attributes in a dictionary." Trying to trace the context by looking through the archive... ok, I see: https://mail.python.org/pipermail/tutor/2015-April/105122.html https://mail.python.org/pipermail/tutor/2015-April/105123.html ... got it.... Ok, so you're replying back to Stephen, about the code snippet he proposed, and you're running into an error. I think I understand better now. Please try changing: print results.asn_registry to the two statements: print results.keys() print results['asn_registry'] The first statement shows what keys are in the results dictionary. The second statement tries to print the value associated with 'asn_registry'. The reason that the original suggestion didn't work here is because, in Python, object attribute lookup is different from dictionary lookup. We guessed that 'results' was an object, and that you wanted to look up the 'asn_registry' attribute of that object. But from the error message, we see that 'results' is a dictionary. Easy to correct. You want to use a dictionary lookup instead. The first print statement is there just to validate that there is such a key 'asn_registry' within the 'results'. It's possible that the key is different, so the first print is there just as a double-check for us. From cybervigilante at gmail.com Sun Apr 26 01:38:33 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 25 Apr 2015 16:38:33 -0700 Subject: [Tutor] REPL format Message-ID: I'm curious why, when I read and decode a binary file from the net in one fell swoop, the REPL prints it between parentheses, line by line but with no commas, like a defective tuple. I can see breaking lines visually, at \n, but if the parentheses don't mean anything I can't see including them. Or do they mean something I've missed? Also, it's interesting that although HTML is case-free, you have to get the case right for the java server page. getbusesforroute.jsp doesn't work. ?import urllib.request u = urllib.request.urlopen(' http://ctabustracker.com/bustime/map/getBusesForRoute.jsp?route=22') data = u.read() f = open('rt22.xml', 'wb') f.write(data) f.close() f = open('rt22.xml', 'rb') transit_info = str(f.read(), encoding='utf-8') >>> transit_info ('\r\n' '\r\n' '\r\n' ... bunch of stuff ... '\t\t\t222 \t\r\n' '\t\t\r\n' '\r\n' '\r\n' '\r\n' '\t\r\n') -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From dyoo at hashcollision.org Sun Apr 26 02:38:58 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Sat, 25 Apr 2015 17:38:58 -0700 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: On Sat, Apr 25, 2015 at 4:38 PM, Jim Mooney wrote: > I'm curious why, when I read and decode a binary file from the net in one > fell swoop, the REPL prints it between parentheses, line by line but with > no commas, like a defective tuple. The REPL is trying to be nice here. What you're seeing is a representation that's using a little-known Python syntactic feature: string literals can be spread across lines. See: https://docs.python.org/2/reference/lexical_analysis.html#string-literal-concatenation At the program's parse time, the Python compiler will join adjacent string literals automatically. It's a cute-but-nasty trick that some other languages do, such as C++. I would strongly discourage not using it yourself in your own programs: it's the source of a very common mistake. Here's an example: #################### def f(x, y): print(x) print(y) f("hello" "world") #################### What do you expect to see? What do you see? So that's why I don't like this feature: makes it really hard to catch mistakes when one is passing string literals as arguments and forgets the comma. Especially nasty when the function being called uses optional arguments. But I'm surprised, frankly, that you're seeing the standard Python REPL using string literal concatenation, as in my memory, it was a lot less accommodating. Is this Python 3? From dyoo at hashcollision.org Sun Apr 26 02:42:15 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Sat, 25 Apr 2015 17:42:15 -0700 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: > I would strongly discourage not using it yourself in your own > programs. Ugh. There was one too many negations there. I deserved to make that mistake, since my sentence structure was unnecessarily nested. :P I meant to say: "I would strongly discourage using literal string concatenation in your own programs: it's the source of a very common mistake..." From alan.gauld at btinternet.com Sun Apr 26 02:43:23 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 26 Apr 2015 01:43:23 +0100 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: On 26/04/15 00:38, Jim Mooney wrote: > ...it's interesting that although > HTML is case-free, you have to get the case right for the java server page. > getbusesforroute.jsp doesn't work. That's because its a file name and has nothing to do with HTML. The HTML is what's inside the file. > ?import urllib.request > u = urllib.request.urlopen(' > http://ctabustracker.com/bustime/map/getBusesForRoute.jsp?route=22') > data = u.read() What do you get if you print data here? That will tell you whether its something to do with that you get from the server or whether its to do with what you are doing to the data when you save/read it. > f = open('rt22.xml', 'wb') > f.write(data) > f.close() > > f = open('rt22.xml', 'rb') > transit_info = str(f.read(), encoding='utf-8') > >>>> transit_info > ('\r\n' > '\r\n' > '\r\n' > ... bunch of stuff ... > '\t\t\t222 \t\r\n' > '\t\t\r\n' I can't reproduce this format in the interpreter so I don't know what's going on. I seem to recall you are using Python 3, is that correct? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From ben+python at benfinney.id.au Sun Apr 26 03:03:22 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Sun, 26 Apr 2015 11:03:22 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest_mode=E2=80=9D_be?= =?utf-8?q?fore_participating_=28was=3A_Tutor_Digest=2C_Vol_134=2C_Issue_8?= =?utf-8?q?6=29?= References: Message-ID: <85lhhfk8f9.fsf_-_@benfinney.id.au> Juanald Reagan writes: > Okay, so it doesn't look like that worked...here is the traceback. I don't > understand the second part of your request. Juanold, to keep the context and thread of the discussion, please respond to individual messages, not digests. To do that, you first need to disable ?digest mode? on your subscription. Change your settings by logging in here . Digest mode should only ever be used if you know for certain you will never be responding to any message. -- \ ?I moved into an all-electric house. I forgot and left the | `\ porch light on all day. When I got home the front door wouldn't | _o__) open.? ?Steven Wright | Ben Finney From robertvstepp at gmail.com Sun Apr 26 04:55:12 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 25 Apr 2015 21:55:12 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: References: <201504242000.t3OK0OoB001036@fido.openend.se> <201504250820.t3P8KplL021923@fido.openend.se> Message-ID: On Sat, Apr 25, 2015 at 10:58 AM, boB Stepp wrote: > On Sat, Apr 25, 2015 at 3:20 AM, Laura Creighton wrote: >> In a message of Fri, 24 Apr 2015 20:24:38 -0500, boB Stepp writes: >>>I think that I can get an exception here (See a post in response that >>>I made earlier today.). What I am *certain* of, is that I cannot >>>install anything on our clinical planning environment. The Solaris >>>workstation that I now have all to myself--I'm thinking they will now >>>let me do what I want with it. But I must double check... But anything >>>I develop there *should* work in the clinical environment. The >>>planning software is the same though that may change soon as there are >>>plans to go up a version and they may not want to do that on my >>>testing/development machine. >> >> This thought 'if it works here, it ought to work there' is an unworthy >> thought for somebody who has learned to test their code. ;) You go to your >> new machine. You pull down your tests and your code. You run all your >> tests. When they pass, you don't just _think_ that the code _ought to_ >> run here -- you _know_ the code will run because it passes all its tests. > > You have a very gentle way of chastising me! ~(:>)) While driving around doing chores today, I realized that I have been incredibly dense here! Of course I can carry my testing suites, etc., over to the production environment: This is will be all part of my code base, which I AM allowed to implement. Duh! If all Python standard libraries are installed on the two Python environments (2.4 and 2.6), then testing should not be an issue, other than taking the time to backtrack and get it going. Now VCS/DVCS programs is another matter entirely, but after hearing Laura's and Alan's input, one or both these solutions can surely be implemented. But is even this an issue? If I do my actual code writing on my Windows PC on which I AM allowed to install Git or whatever, and FTP the code to run to either the 810X or the production SE environments, then I will always have version control in place. I reread Steven's post tonight, and he actually answered affirmatively to this question; it just did not penetrate until this evening. boB From robertvstepp at gmail.com Sun Apr 26 05:09:44 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 25 Apr 2015 22:09:44 -0500 Subject: [Tutor] Introductory questions on test-driven development and implementing Git version control. In-Reply-To: <20150425003654.GB5663@ando.pearwood.info> References: <20150425003654.GB5663@ando.pearwood.info> Message-ID: On Fri, Apr 24, 2015 at 7:36 PM, Steven D'Aprano wrote: > So many questions... let's hope I don't miss any... :-) > > On Fri, Apr 24, 2015 at 02:09:45PM -0500, boB Stepp wrote: > >> First question: What testing modules/frameworks should I start out >> with? Doing a quick scan of the books I have, mention is made of >> doctest and unittest modules in the Python standard libraries. But >> mention is also made of two third party modules, nose and pytest. > [...] > unittest is quite easy to use, and powerful. Some people complain that > it is not very Pythonic, but I've never felt that. It is also based on a > standard and much-copied Java library, so there are versions of unittest > for many different languages. I quite like it. I will definitely start out my learning by going this route. Will work at work (Though Monday I must do an actual import of unittest to ensure it is actually on both environments. Ya never know...) and also at home. >> And as to automated testing: I really, ..., really would like to >> implement it on my side projects at work. But all such programs start >> in a proprietary scripting environment, which can call external Python >> (or other languages) scripts. The resulting final program is almost >> always an unavoidable amount of propriety scripting language (Which I >> always strive to minimize the amount of.), Solaris shell >> commands/scripts and Python. As I have been learning more Python and >> implementing it at work, I have found that the most successful >> approach seems to be to first get all of the information I need out of >> the CSA (commercial software environment) upfront, save it in temp >> files, then call a Python script to start the heavy duty processing, >> do everything possible in Python, generate a "reload" script file that >> contains language the CSA understands, and finally run that inside the >> CSA. How do I go about automating the testing of something like this? >> And apply TDD write tests first principles? > > TDD principles apply to any programming language. So long as the > language that you use to write the tests has ways of calling your shell > scripts and CSA code, and seeing what results they get, you can test > them. CSA scripting can indeed call both its own scripts and external (to the CSA) ones. But everything must start within the CSA, or none of the CSA's scripts that are part of the overall program can be called. As far as I know, there is no way to initiate a CSA script from the outside, though just to double check I might post that question on the CSA's Google group. > However, I *religiously* write the documentation first. If I don't > document what the function does, how will I know what the code should > do or when I am finished? Every day I code this sinks more deeply into my bones... -- boB From robertvstepp at gmail.com Sun Apr 26 05:16:18 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Sat, 25 Apr 2015 22:16:18 -0500 Subject: [Tutor] Questions (and initial responses) on using version control [Was: Introductory questions on test-driven development and implementing Git version control.] In-Reply-To: References: Message-ID: On Sat, Apr 25, 2015 at 10:30 AM, boB Stepp wrote: > On Fri, Apr 24, 2015 at 7:36 PM, Steven D'Aprano wrote: >>On Fri, Apr 24, 2015 at 02:09:45PM -0500, boB Stepp wrote: > > [...] > >>> And what would be the best approach to integrating Git with these >>> efforts? Just how often does one commit one's code to the version >>> control system? Or do I have some GCEs (Gross Conceptual Errors) here? >>> Can Git be set up to automatically keep track of my code as I create >>> and edit it? [...] >>The executive summary of how I use version control: > >>- work on bite-sized chunks of functionality >>- when the tests all pass, commit the work done >>- push changes to the master repo at least once per day > > >>The way I use version control on my own is that I have typically use a >>single branch. I rarely have to worry about contributions from others, >>so it's just my changes. Make sure that all the relevent files (source >>code, documentation, tests, images, etc.) are being tracked. Static >>files which never change, like reference materials, should not be. > >>Starting from a point where all the tests pass, I decide to work on a >>new feature, or fix a bug. A feature might be something as small as "fix >>the documentation for this function", but *not* as big as "control >>remote controlled space ship" -- in other words, a bite-sized chunk of >>work, not a full meal. I write some tests, and write the minimal amount >>of code code that makes those tests pass: > >>- write tests >>- save tests >>- write code >>- save code >>- run tests >>- fix bugs in tests >>- save tests >>- write some more code >>- save code >>- run tests again >>- write some more code >>- save code >>- run tests again > > >>etc. Once the tests pass, then I have a feature and/or bug fix, and I >>commit all the relevent changes to the VCS. hg automatically tracks >>files, git requires you to remind it every single time what files are >>being used, but either way, by the time I run `hg commit` or `git >>commit` I have a complete, and hopefully working, bite-sized chunk of >>code that has an obvious commit message: > >>"fix bug in spam function" >>"correct spelling errors in module docs" >>"rename function ham to spam" >>"change function eggs from using a list to a dict" >>"move class K into its own submodule" > >>etc. Notice that each change is small enough to encapsulate in a short >>description, but big enough that some of them may require multiple >>rounds of back-and-forth code-and-test before it works. > >>I run the tests even after seemingly innoculous changes to comments or >>docstrings, especially docstrings. Edits to a docstring may break your >>doctests, or even your code, if you accidentally break the quoting. > >>Then, when I am feeling satisfied that I've done a sufficiently large >>amount of work, I then push those changes to the master repo (if any). >>This allows me to work from various computers and still share the same >>code base. "Sufficiently large" may mean a single change, or a full >>day's work, or a whole lot of related changes that add up to one big >>change, whatever you prefer. But it shouldn't be less than once per day. Thanks for taking the time to share your workflow. It is very helpful for me. > [...] > >>> And I would like to have all of that under version control, too. But >>> while I am allowed to write my own programs for this CSA, I am not >>> allowed to install anything else, strange as this may sound! Since the >>> only functional editors in these bare-bones Solaris 10 environments >>> are some simplistic default editor that I do not know the name of and >>> vi, I long ago gravitated to doing my actual coding on my Windows PC >>> (Being careful to save things with Unix line endings.) and FTPing to >>> the environments where these programs will actually run. I AM allowed >>> to install anything I want (within reason)on my PC. So I am thinking >>> install and use Git there? > >>Yes. This is what I plan to do. I have started reading the free online book, "Pro Git--Everything You Need to Know About Git, 2nd ed., c2014, which is accessible via the Git website. I also watched the video about Git for 4-year olds. Long video, but it gave a good overview of the Git way of implementing things. Again, thanks! I think that after reading the first two chapters of the book, I will know more than enough to get started. In actuality, after watching the video last night, I could probably get going now. But I am an inveterate book reader... boB From steve at pearwood.info Sun Apr 26 06:28:04 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 14:28:04 +1000 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: <20150426042804.GI5663@ando.pearwood.info> On Sat, Apr 25, 2015 at 04:38:33PM -0700, Jim Mooney wrote: > I'm curious why, when I read and decode a binary file from the net in one > fell swoop, the REPL prints it between parentheses, line by line but with > no commas, like a defective tuple. What REPL are you using? I can't reproduce what you are reporting in the standard Python 3.3 interactive interpreter. When I print the transit_info I get a single block of text: '\r\n\r\n ... \r\n' which my terminal then wraps over multiple lines. > I can see breaking lines visually, at > \n, but if the parentheses don't mean anything I can't see including them. > Or do they mean something I've missed? Also, it's interesting that although > HTML is case-free, you have to get the case right for the java server page. > getbusesforroute.jsp doesn't work. That has nothing to do with HTML. HTML is a file format, and it is case-insensitive. and are the same tag. But the http protocol has nothing to do with the contents of the files. When you give a URL like: http://ctabustracker.com/bustime/map/getBusesForRoute.jsp?route=22 parts of it are case-insensitive and parts may not be. The domain part: ctabustracker.com is handled by the DNS system, and is case-insensitive. You could write http://cTaBuStRaCkEr.CoM/ if you like, and it would give you the same result. But the part after the domain is controlled by the web server for that domain, and that depends on the web server. Some web servers may choose to be case-insensitive. Others may be case-sensitive. The local part of the URL that follows the domain is under control of the web server, which could do anything it likes. -- Steve From steve at pearwood.info Sun Apr 26 10:38:39 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 18:38:39 +1000 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: <20150426083838.GJ5663@ando.pearwood.info> On Sat, Apr 25, 2015 at 05:38:58PM -0700, Danny Yoo wrote: > On Sat, Apr 25, 2015 at 4:38 PM, Jim Mooney wrote: > > I'm curious why, when I read and decode a binary file from the net in one > > fell swoop, the REPL prints it between parentheses, line by line but with > > no commas, like a defective tuple. > > > The REPL is trying to be nice here. What you're seeing is a > representation that's using a little-known Python syntactic feature: > string literals can be spread across lines. See: > > https://docs.python.org/2/reference/lexical_analysis.html#string-literal-concatenation > > At the program's parse time, the Python compiler will join adjacent > string literals automatically. It's not specifically across lines. Any two adjacent string literals will be concatenated, even if they have different string delimiters: '"You can' "'t do that!" '" he said.' is arguable somewhat nicer than either of these alternatives: '"You can\'t do that!" he said.' "\"You can't do that!\" he said." (Well, to be completely honest, I don't that *any* of the solutions to the problem of using both sorts of quotation marks in the same string is nice, but its good to have options.) Where automatic concatenation of string literals really comes into its own is when you have a long template string or error message, for example, which won't fit on a single line: message = "Doh, a deer, a female deer; Ray, a drop of golden sun; Me, a name I call myself; Far, a long long way to run; So, a needle pulling thread; La, a note to follow So; Tea, a drink with jam and bread." We could use a triple quoted string: message = """Doh, a deer, a female deer; Ray, a drop of golden sun; Me, a name I call myself; Far, a long long way to run; So, a needle pulling thread; La, a note to follow So; Tea, a drink with jam and bread.""" But that not only includes line breaks, but the second line onwards is indented. We can break it up into substrings, and using a surrounding pair of round brackets to continue the expression over multiple lines, we can then use explicit concatenation: message = ("Doh, a deer, a female deer;" + " Ray, a drop of golden sun;" + " Me, a name I call myself;" + " Far, a long long way to run;" + " So, a needle pulling thread;" + " La, a note to follow So;" + " Tea, a drink with jam and bread." ) but that has the disadvantage that the concatenation may be performed at runtime. (In fact, recent versions of CPython will do that at compile time, but it is not guaranteed by the language. Past versions did not; future versions may not, and other implementations like PyPy, IronPython, Jython and others may not either.) To my mind, the least unpleasant version is this one, using implicit concatenation: message = ( "Doh, a deer, a female deer; Ray, a drop of golden sun;" " Me, a name I call myself; Far, a long long way to run;" " So, a needle pulling thread; La, a note to follow So;" " Tea, a drink with jam and bread." ) > It's a cute-but-nasty trick that some other languages do, such as C++. > > > I would strongly discourage not using it yourself in your own > programs: it's the source of a very common mistake. Here's an > example: I agree that this is a feature which can be abused and misused, but I disagree with Danny about avoiding it. I think that it works very well in the above example. > So that's why I don't like this feature: makes it really hard to catch > mistakes when one is passing string literals as arguments and forgets > the comma. Especially nasty when the function being called uses > optional arguments. I acknowledge that this scenario can and does happen in real life, but I don't think it is common. It only occurs when you have two consecutive arguments which are both string literals, and you forget the comma between them. How often does that happen? It cannot occur if one or more of the arguments are variables: greeting = "Hello " function(greeting "world!") # Syntax error. -- Steve From cybervigilante at gmail.com Sun Apr 26 03:28:46 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 25 Apr 2015 18:28:46 -0700 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: On 25 April 2015 at 17:43, Alan Gauld wrote: > know what's going on. I seem to recall you are using Python 3, > is that correct? > > I guess I should specify from now on py3 on win xp Another question - why does the first assignment work but not the second. I can see it's a syntax error but if Py can unpack in the first case why can't it unpack the same thing in the second? >>> a, *b = 'good', 'bad', 'ugly' >>> a 'good' >>> b ['bad', 'ugly'] >>> a, *b = 'ham', 'eggs', 'spam' >>> a 'ham' >>> b ['eggs', 'spam'] >>> *b = 'eggs', 'spam' SyntaxError: starred assignment target must be in a list or tuple >>> -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From cybervigilante at gmail.com Sun Apr 26 03:45:55 2015 From: cybervigilante at gmail.com (Jim Mooney) Date: Sat, 25 Apr 2015 18:45:55 -0700 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest_mode=E2=80=9D_be?= =?utf-8?q?fore_participating_=28was=3A_Tutor_Digest=2C_Vol_134=2C_?= =?utf-8?q?Issue_86=29?= In-Reply-To: <85lhhfk8f9.fsf_-_@benfinney.id.au> References: <85lhhfk8f9.fsf_-_@benfinney.id.au> Message-ID: On 25 April 2015 at 18:03, Ben Finney wrote: > Digest mode should only ever be used if you know for certain you will > never be responding to any message. > That brings up a great shortcut if you use gmail. If you select some text before reply that's All that is sent. Cuts way down on huge reply chains, and saves mooching through your reply to delete all the garbola. However, it has to be enabled in google labs: http://blog.jgc.org/2013/01/the-greatest-google-mail-feature-you.html I just used it to quote only the three lines above (if I got it right ;') It could be some other mail services have this, too. You'd have to look. -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From cybervigilante at gmail.com Sun Apr 26 06:18:53 2015 From: cybervigilante at gmail.com (Jim Mooney Py3winXP) Date: Sat, 25 Apr 2015 21:18:53 -0700 Subject: [Tutor] output is all integer when there should be some floats Message-ID: It seems odd to me that there are three tests to see if user input is digits - isdecimal, isdigit, isnumeric, but nothing to test for a float unless you use a try - except. Or did I miss something? Anyway, I tried a try - except, but I don't see why my output is all integer when I only convert to integer if it passes the is_integer test: user_values = [] while True: user_input = input("Give me a number: ") if user_input.lower() == 'done': break try: user_input = float(user_input) if user_input.is_integer: user_input = int(user_input) user_values.append(user_input) except Exception as err: print("You entered {0}, which is not a valid number: error - {1}".format(user_input, err)) continue print("Your entered numbers were {0}".format(user_values)) #only integers print, even when I entered some floats -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From cybervigilante at gmail.com Sun Apr 26 07:03:29 2015 From: cybervigilante at gmail.com (Jim Mooney Py3winXP) Date: Sat, 25 Apr 2015 22:03:29 -0700 Subject: [Tutor] REPL format In-Reply-To: <20150426042804.GI5663@ando.pearwood.info> References: <20150426042804.GI5663@ando.pearwood.info> Message-ID: On 25 April 2015 at 21:28, Steven D'Aprano wrote: > What REPL are you using? I can't reproduce what you are > reporting in the standard Python 3.3 interactive interpreter. When I > print the transit_info I get a single block of text: > Ah, found the problem. I was looking at PyScripter output. When I ran it from the console and immediately went into interpreter mode to look at the transit_info, I got the block of text. I have to remember to go to the console if I'm befuddled by output ;') Although I really like PyScripter. I tried the free PyCharm but it involves a lot of garbola and slows me down at my level. Free Wing is missing a lot of conveniences, like commenting out a whole block. All the other free editors had various problems. Just my opinion. A side note on using Py3, which I now have in my header so I don't have to keep mentioning it - I decided to use it since most big modules are ported but I just found out the all-important google api is py 2 only. Bummer. Odd that google was the major mover in killing IE6 but isn't moving ahead on Python. PayPal does Py3, though. -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From jon.engle at gmail.com Sun Apr 26 05:02:56 2015 From: jon.engle at gmail.com (Juanald Reagan) Date: Sat, 25 Apr 2015 23:02:56 -0400 Subject: [Tutor] Tutor Digest, Vol 134, Issue 89 In-Reply-To: References: Message-ID: Sorry for not providing all the relevant info, let me provide some additional details: When I run this code: from ipwhois import IPWhois file=open('ip.txt', 'r') ipaddy=file.read() obj = IPWhois(ipaddy) results = [obj.lookup()] print results [0] I receive this output: Jons-computer:whois-0.7 2 jon$ python pythonwhois.py {'asn_registry': 'arin', 'asn_date': '', 'asn_country_code': 'US', 'raw': None, 'asn_cidr': '8.8.8.0/24', 'raw_referral': None, 'query': '8.8.8.8', 'referral': None, 'nets': [{'updated': '2012-02-24T00:00:00', 'handle': 'NET-8-0-0-0-1', 'description': 'Level 3 Communications, Inc.', 'tech_emails': 'ipaddressing at level3.com', 'abuse_emails': 'abuse at level3.com', 'postal_code': '80021', 'address': '1025 Eldorado Blvd.', 'cidr': '8.0.0.0/8', 'city': 'Broomfield', 'name': 'LVLT-ORG-8-8', 'created': '1992-12-01T00:00:00', 'country': 'US', 'state': 'CO', 'range': '8.0.0.0 - 8.255.255.255', 'misc_emails': None}, {'updated': '2014-03-14T00:00:00', 'handle': 'NET-8-8-8-0-1', 'description': 'Google Inc.', 'tech_emails': ' arin-contact at google.com', 'abuse_emails': 'arin-contact at google.com', 'postal_code': '94043', 'address': '1600 Amphitheatre Parkway', 'cidr': ' 8.8.8.0/24', 'city': 'Mountain View', 'name': 'LVLT-GOGL-8-8-8', 'created': '2014-03-14T00:00:00', 'country': 'US', 'state': 'CA', 'range': None, 'misc_emails': None}], 'asn': '15169'} I would like to refine this information and only receive these fields as my output: {'asn_registry': 'arin',description': 'Google Inc.',} I was hoping there was a way to take each one of these items and read them into a list so I can pick and choose the fields I want by index. I believe all fields are currently stored in index position 0. Here are the helper file contents: | Args: | inc_raw: Boolean for whether to include the raw whois results in | the returned dictionary. | retry_count: The number of times to retry in case socket errors, | timeouts, connection resets, etc. are encountered. | get_referral: Boolean for whether to retrieve referral whois | information, if available. | extra_blacklist: A list of blacklisted whois servers in addition to | the global BLACKLIST. | ignore_referral_errors: Boolean for whether to ignore and continue | when an exception is encountered on referral whois lookups. | | Returns: | Dictionary: A dictionary containing the following keys: | query (String) - The IP address. | asn (String) - The Autonomous System Number. | asn_date (String) - The ASN Allocation date. | asn_registry (String) - The assigned ASN registry. | asn_cidr (String) - The assigned ASN CIDR. | asn_country_code (String) - The assigned ASN country code. | nets (List) - Dictionaries containing network information | which consists of the fields listed in the NIC_WHOIS | dictionary. Certain IPs have more granular network | listings, hence the need for a list object. | raw (String) - Raw whois results if the inc_raw parameter | is True. | referral (Dictionary) - Dictionary containing referral | whois information if get_referral is True and the | server isn't blacklisted. Consists of fields listed | in the RWHOIS dictionary. Additional referral server | informaion is added in the server and port keys. | raw_referral (String) - Raw referral whois results if the | inc_raw parameter is True. | | *lookup_rws*(self, inc_raw=False, retry_count=3) | The function for retrieving and parsing whois information for an IP | address via HTTP (Whois-RWS). | | NOTE: This should be faster than IPWhois.lookup(), but may not be as | reliable. AFRINIC does not have a Whois-RWS service yet. We have | to rely on the Ripe RWS service, which does not contain all of the | data we need. LACNIC RWS is in beta v2. | | Args: | inc_raw: Boolean for whether to include the raw whois results in | the returned dictionary. | retry_count: The number of times to retry in case socket errors, | timeouts, connection resets, etc. are encountered. | | Returns: | Dictionary: A dictionary containing the following keys: | query (String) - The IP address. | asn (String) - The Autonomous System Number. | asn_date (String) - The ASN Allocation date. | asn_registry (String) - The assigned ASN registry. | asn_cidr (String) - The assigned ASN CIDR. | asn_country_code (String) - The assigned ASN country code. | nets (List) - Dictionaries containing network information | which consists of the fields listed in the NIC_WHOIS | dictionary. Certain IPs have more granular network | listings, hence the need for a list object. | raw (Dictionary) - Whois results in Json format if the | inc_raw parameter is True. On Sat, Apr 25, 2015 at 8:43 PM, wrote: > Send Tutor mailing list submissions to > tutor at python.org > > To subscribe or unsubscribe via the World Wide Web, visit > https://mail.python.org/mailman/listinfo/tutor > or, via email, send a message with subject or body 'help' to > tutor-request at python.org > > You can reach the person managing the list at > tutor-owner at python.org > > When replying, please edit your Subject line so it is more specific > than "Re: Contents of Tutor digest..." > > > Today's Topics: > > 1. Re: whois github package (Alan Gauld) > 2. Looking up a value in a dictionary (Danny Yoo) > 3. REPL format (Jim Mooney) > 4. Re: REPL format (Danny Yoo) > 5. Re: REPL format (Danny Yoo) > 6. Re: REPL format (Alan Gauld) > > > ---------------------------------------------------------------------- > > Message: 1 > Date: Sun, 26 Apr 2015 00:25:59 +0100 > From: Alan Gauld > To: tutor at python.org > Subject: Re: [Tutor] whois github package > Message-ID: > Content-Type: text/plain; charset=windows-1252; format=flowed > > On 25/04/15 14:46, Juanald Reagan wrote: > > Hello! I have a question regarding how to use/implement a package found > at > > github. > > > > https://github.com/secynic/ipwhois > > > We are not experts on this here since this list s for people learning > the core Python lamguage and its standard library. Howe er I see Steven > has had a go at helping you. > > Another thing you could try is using Pythons built in help() function: > > After > >>> from ipwhois import IPWhois > > Try > >>> help(IPWhois) > > > obj = IPWhois(ipaddy) > > Now try > > >>> help(obj) > >>> help(obj.lookup) > > That might give some clues about what methods exist and what they > return. (Assuming the author included doc strings of course! > > > results = [obj.lookup()] > > print results [0] > > > > This returns ALL the fields not just the "asn_registry" field. > > That's what I'd expect since you put the output of lookup() > as the first element of the list. You then printed that element. > > But if you showed us even a snippet of what that actually > looked like it would help us answer your question about > how to access it. Remember we don't know this package so > you have to show us what is happening not just summarize > what you think its doing. > > > I looked for documentation on github > > Python documentation is often embedded in the module/objects > help() will often reveal it. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > > > ------------------------------ > > Message: 2 > Date: Sat, 25 Apr 2015 16:38:15 -0700 > From: Danny Yoo > To: Juanald Reagan > Cc: "tutor at python.org" > Subject: [Tutor] Looking up a value in a dictionary > Message-ID: > < > CAGZAPF4VBGQRSvvKFrtpayLxh8pcM85zYdLDwSreuDAzPXD5-g at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > On Sat, Apr 25, 2015 at 11:13 AM, Juanald Reagan > wrote: > > Okay, so it doesn't look like that worked...here is the traceback. I > don't > > understand the second part of your request. > > > > Jons-desktop:whois-0.7 2 jon$ python pythonwhois.py > > > > 8.8.8.8 > > > > Traceback (most recent call last): > > > > File "pythonwhois.py", line 14, in > > > > print results.asn_registry > > > > AttributeError: 'dict' object has no attribute 'asn_registry' > > > Because of the lack of subject-line context, I'm having a hard time > following this thread. I've changed the subject to "Looking up > attributes in a dictionary." Trying to trace the context by looking > through the archive... ok, I see: > > https://mail.python.org/pipermail/tutor/2015-April/105122.html > https://mail.python.org/pipermail/tutor/2015-April/105123.html > > ... got it.... > > > Ok, so you're replying back to Stephen, about the code snippet he > proposed, and you're running into an error. I think I understand > better now. > > > Please try changing: > > print results.asn_registry > > to the two statements: > > print results.keys() > print results['asn_registry'] > > > The first statement shows what keys are in the results dictionary. > The second statement tries to print the value associated with > 'asn_registry'. > > The reason that the original suggestion didn't work here is because, > in Python, object attribute lookup is different from dictionary > lookup. We guessed that 'results' was an object, and that you wanted > to look up the 'asn_registry' attribute of that object. > > But from the error message, we see that 'results' is a dictionary. > Easy to correct. You want to use a dictionary lookup instead. > > The first print statement is there just to validate that there is such > a key 'asn_registry' within the 'results'. It's possible that the key > is different, so the first print is there just as a double-check for > us. > > > ------------------------------ > > Message: 3 > Date: Sat, 25 Apr 2015 16:38:33 -0700 > From: Jim Mooney > To: "tutor at python.org" > Subject: [Tutor] REPL format > Message-ID: > Y9yJBwbWeSA at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > I'm curious why, when I read and decode a binary file from the net in one > fell swoop, the REPL prints it between parentheses, line by line but with > no commas, like a defective tuple. I can see breaking lines visually, at > \n, but if the parentheses don't mean anything I can't see including them. > Or do they mean something I've missed? Also, it's interesting that although > HTML is case-free, you have to get the case right for the java server page. > getbusesforroute.jsp doesn't work. > > ?import urllib.request > u = urllib.request.urlopen(' > http://ctabustracker.com/bustime/map/getBusesForRoute.jsp?route=22') > data = u.read() > f = open('rt22.xml', 'wb') > f.write(data) > f.close() > > f = open('rt22.xml', 'rb') > transit_info = str(f.read(), encoding='utf-8') > > >>> transit_info > ('\r\n' > '\r\n' > '\r\n' > ... bunch of stuff ... > '\t\t\t222 \t\r\n' > '\t\t\r\n' > '\r\n' > '\r\n' > '\r\n' > '\t\r\n') > > > > -- > Jim > > If you only had one hour left to live, would you spend it on Facebook, > Twitter, or Google Plus? > > > ------------------------------ > > Message: 4 > Date: Sat, 25 Apr 2015 17:38:58 -0700 > From: Danny Yoo > To: Jim Mooney > Cc: "tutor at python.org" > Subject: Re: [Tutor] REPL format > Message-ID: > < > CAGZAPF4PpHP6cGCnm3UwhbjdB8u75kba5BoyYTe1hWcxk8aAGg at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > On Sat, Apr 25, 2015 at 4:38 PM, Jim Mooney > wrote: > > I'm curious why, when I read and decode a binary file from the net in one > > fell swoop, the REPL prints it between parentheses, line by line but with > > no commas, like a defective tuple. > > > The REPL is trying to be nice here. What you're seeing is a > representation that's using a little-known Python syntactic feature: > string literals can be spread across lines. See: > > > https://docs.python.org/2/reference/lexical_analysis.html#string-literal-concatenation > > At the program's parse time, the Python compiler will join adjacent > string literals automatically. > > > It's a cute-but-nasty trick that some other languages do, such as C++. > > > I would strongly discourage not using it yourself in your own > programs: it's the source of a very common mistake. Here's an > example: > > #################### > def f(x, y): > print(x) > print(y) > > f("hello" > "world") > #################### > > What do you expect to see? What do you see? > > So that's why I don't like this feature: makes it really hard to catch > mistakes when one is passing string literals as arguments and forgets > the comma. Especially nasty when the function being called uses > optional arguments. > > > But I'm surprised, frankly, that you're seeing the standard Python > REPL using string literal concatenation, as in my memory, it was a lot > less accommodating. Is this Python 3? > > > ------------------------------ > > Message: 5 > Date: Sat, 25 Apr 2015 17:42:15 -0700 > From: Danny Yoo > To: Jim Mooney > Cc: "tutor at python.org" > Subject: Re: [Tutor] REPL format > Message-ID: > FWeESEw at mail.gmail.com> > Content-Type: text/plain; charset=UTF-8 > > > I would strongly discourage not using it yourself in your own > > programs. > > Ugh. There was one too many negations there. I deserved to make that > mistake, since my sentence structure was unnecessarily nested. :P > > I meant to say: "I would strongly discourage using literal string > concatenation in your own programs: it's the source of a very common > mistake..." > > > ------------------------------ > > Message: 6 > Date: Sun, 26 Apr 2015 01:43:23 +0100 > From: Alan Gauld > To: tutor at python.org > Subject: Re: [Tutor] REPL format > Message-ID: > Content-Type: text/plain; charset=windows-1252; format=flowed > > On 26/04/15 00:38, Jim Mooney wrote: > > > ...it's interesting that although > > HTML is case-free, you have to get the case right for the java server > page. > > getbusesforroute.jsp doesn't work. > > That's because its a file name and has nothing to do with HTML. > The HTML is what's inside the file. > > > ?import urllib.request > > u = urllib.request.urlopen(' > > http://ctabustracker.com/bustime/map/getBusesForRoute.jsp?route=22') > > data = u.read() > > What do you get if you print data here? > That will tell you whether its something to do with that you > get from the server or whether its to do with what you are > doing to the data when you save/read it. > > > f = open('rt22.xml', 'wb') > > f.write(data) > > f.close() > > > > f = open('rt22.xml', 'rb') > > transit_info = str(f.read(), encoding='utf-8') > > > >>>> transit_info > > ('\r\n' > > '\r\n' > > '\r\n' > > ... bunch of stuff ... > > '\t\t\t222 \t\r\n' > > '\t\t\r\n' > > I can't reproduce this format in the interpreter so I don't > know what's going on. I seem to recall you are using Python 3, > is that correct? > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > > > ------------------------------ > > Subject: Digest Footer > > _______________________________________________ > Tutor maillist - Tutor at python.org > https://mail.python.org/mailman/listinfo/tutor > > > ------------------------------ > > End of Tutor Digest, Vol 134, Issue 89 > ************************************** > -- Cheers, Jon S. Engle jon.engle at gmail.com From smarugg at gmail.com Sun Apr 26 05:23:44 2015 From: smarugg at gmail.com (Spencer For Friends) Date: Sat, 25 Apr 2015 23:23:44 -0400 Subject: [Tutor] Python tkinter. Opening another script from main window stop main window from functioning. Looking for Help Message-ID: Hi all. I'm new to Python and I'm trying my best to learn, but I'm really struggling with some problems. I'm using a tkinter window with a button on it to open another Python script. When the button is clicked and the new script loads it opens up it's own window over top of my tkinter window. The problem is, when I switch back to my tkinter window, none of the buttons are click-able anymore. The whole windows is unresponsive. The click animation on the button doesn't even function. Any help to resolve this would be greatly appreciated. Here is my code. from Tkinter import * from PIL import ImageTk, Image import os from magicassistantcsv import MagicAssistantCSV CSV_FILE = "data/inventory.csv" csv = MagicAssistantCSV(CSV_FILE, append=True) root = Tk() #Add POP Logo Image To Screen POPimg = ImageTk.PhotoImage(Image.open("images/poplogo.png")) panel = Label(root, image = POPimg) panel.grid(row=0, column =0, sticky=W) #Add Magic Logo Image mtgimg = ImageTk.PhotoImage(Image.open("images/mtgcardbot.png")) panel = Label(root, image = mtgimg) panel.grid(row=1, column =0, sticky=W, padx=300, pady=180) #Make Window Full Screen w, h = root.winfo_screenwidth(), root.winfo_screenheight() root.overrideredirect(1) root.geometry("%dx%d+0+0" % (w, h)) #Add Execute Functionality To Button def callback(): execfile("test.py") def endTrade(): csv.close() button1 = Button(text = 'Scan Your Card!', font=('Arial', '20'), fg = 'red', command = callback) button2 = Button(text = 'Scan Complete', font=('Arial', '20'), fg = 'red', command = endTrade) #Configure Button Sizes button1.config( height = 3, width = 25 ) button2.config( height = 3, width = 25 ) #Display Buttons On Screen button1.grid(row=1, column=0, sticky = S, padx=616) button2.grid(row=2, column=0) root.mainloop() Kind Regards -Spencer From steve at pearwood.info Sun Apr 26 13:02:57 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 21:02:57 +1000 Subject: [Tutor] output is all integer when there should be some floats In-Reply-To: References: Message-ID: <20150426110256.GK5663@ando.pearwood.info> On Sat, Apr 25, 2015 at 09:18:53PM -0700, Jim Mooney Py3winXP wrote: > It seems odd to me that there are three tests to see if user input is > digits - isdecimal, isdigit, isnumeric, but nothing to test for a float > unless you use a try - except. Or did I miss something? Yes -- the string tests don't specifically test for valid numbers, only digit characters. If we go back deep into the mists of time, when dinosaurs ruled the earth, Python ints were not unlimited in size. If you tried to create an integer that was too big, you would get an exception, either an OverflowError or a ValueError depending on what you tried to do. Even today, just because a string is all digits doesn't mean that you can successfully turn it into an int. You may run out of memory, if you have millions of digits. The right way to check is a string is numeric is to try to convert it into a number and see what happens. The string methods are too strict, and will prohibit perfectly good numeric strings: py> s = ' -123 ' py> s.isdigit() False py> int(s) -123 (In my experience, the isdigit etc. methods are really only useful for testing individual characters.) Instead: try: n = int(s) except ValueError: print("failed") or similar. Do you know the difference in meaning between isdigit, isnumeric, and isdecimal? > Anyway, I tried a > try - except, but I don't see why my output is all integer when I only > convert to integer if it passes the is_integer test: That's what you *intended* to do, but it isn't what you did :-) > user_values = [] > while True: > user_input = input("Give me a number: ") > if user_input.lower() == 'done': break > try: > user_input = float(user_input) > if user_input.is_integer: user_input = int(user_input) At the interactive interpreter: py> x = 23.1 py> x.is_integer # no brackets py> x.is_integer() # with brackets False Built-in methods and functions are consider "truthy" values, so your test user_input.is_integer (without the brackets) is always true and the number will always be converted to an int. Personally, I would not do the conversion like that. The big problem is that for sufficiently large integers, floats lose precision: py> s = '123456789012345678901' py> int(s) 123456789012345678901 py> int(float(s)) 123456789012345683968 Instead, I'd create a helper function that first tries to convert to an int, and only if that fails, converts to a float: def make_number(astring): if not isinstance(astring, str): raise TypeError('not a string') for kind in (int, float): try: return kind(astring) except ValueError: pass raise ValueError( 'String {0} is not a supported number.'.format(astring) ) You could support more formats if you like, e.g. 0x123 for hex ints, complex, fractions, percentages, whatever you wanted. But as a simpler string-to-int-or-float function, this works well. -- Steve From steve at pearwood.info Sun Apr 26 13:22:53 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 21:22:53 +1000 Subject: [Tutor] Tutor Digest, Vol 134, Issue 89 In-Reply-To: References: Message-ID: <20150426112253.GL5663@ando.pearwood.info> Hi Juanald, or Jon if you prefer, You're still replying to the digest, which means we're still getting six or eight pages of messages we've already seen. My answer to your question is below: On Sat, Apr 25, 2015 at 11:02:56PM -0400, Juanald Reagan wrote: > Sorry for not providing all the relevant info, let me provide some > additional details: > > When I run this code: > > from ipwhois import IPWhois > file=open('ip.txt', 'r') > ipaddy=file.read() > obj = IPWhois(ipaddy) > results = [obj.lookup()] > print results [0] > > I receive this output: > > Jons-computer:whois-0.7 2 jon$ python pythonwhois.py > > {'asn_registry': 'arin', 'asn_date': '', 'asn_country_code': 'US', 'raw': > None, 'asn_cidr': '8.8.8.0/24', 'raw_referral': None, 'query': '8.8.8.8', [snip output] Awesome! That's the information we needed to see. IPWhois() returns a dictionary of {key: value} pairs. So we can extract the fields you want like this: obj = IPWhois(ipaddy) registry = obj['asn_registry'] description = obj['description'] If you insist on using a list with indexed values, you can do this: obj = IPWhois(ipaddy) results = [obj['asn_registry'], obj['description']] registry = results[0] description = results[1] but in my opinion that's silly since you already have the information in the obj dictionary, copying it into the results list is just a waste of time. Note that this will *not* work: obj = IPWhois(ipaddy) results = list(obj.values()) registry = results[ ???? ] # What index should I use? description = results[ ???? ] because dictionaries are unordered, and you don't know what order the values will be returned. Depending on the version of Python you are using, it might even be a different order every time you run the program. -- Steve From steve at pearwood.info Sun Apr 26 13:30:26 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 21:30:26 +1000 Subject: [Tutor] Python tkinter. Opening another script from main window stop main window from functioning. Looking for Help In-Reply-To: References: Message-ID: <20150426113025.GM5663@ando.pearwood.info> On Sat, Apr 25, 2015 at 11:23:44PM -0400, Spencer For Friends wrote: > Hi all. I'm new to Python and I'm trying my best to learn, but I'm really > struggling with some problems. You've picked a *very* hard problem to solve. I can tell you what's wrong, but I can't tell you how to fix it. I know it can be fixed, but I've never had to do it before. [Thinking aloud... Maybe the subprocess module? ... ] [snip code] > def callback(): > execfile("test.py") Here is your problem: execfile will run a Python program, but it has to wait for that program to finish before it can continue. So your callback is waiting for the test.py program to finish, which I guess means closing its windows. It you want to have test.py run independently of this window, you cannot use execfile. Sorry I can't solve your problem, but at least you now understand it. -- Steve From alan.gauld at btinternet.com Sun Apr 26 13:57:57 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 26 Apr 2015 12:57:57 +0100 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: On 26/04/15 02:28, Jim Mooney wrote: > Another question - why does the first assignment work but not the second. I > can see it's a syntax error but if Py can unpack in the first case why > can't it unpack the same thing in the second? I'm not sure what you expect it to unpack. Its already a variable pointing at a tuple without the *. What do you expect the * to do? >>>> a, *b = 'ham', 'eggs', 'spam' >>>> a > 'ham' >>>> b > ['eggs', 'spam'] >>>> *b = 'eggs', 'spam' > SyntaxError: starred assignment target must be in a list or tuple >>> b = 'eggs', 'spam' >>> b ('eggs', 'spam') -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Sun Apr 26 14:05:28 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 26 Apr 2015 22:05:28 +1000 Subject: [Tutor] REPL format In-Reply-To: References: Message-ID: <20150426120528.GN5663@ando.pearwood.info> On Sun, Apr 26, 2015 at 12:57:57PM +0100, Alan Gauld wrote: > On 26/04/15 02:28, Jim Mooney wrote: > > >Another question - why does the first assignment work but not the second. I > >can see it's a syntax error but if Py can unpack in the first case why > >can't it unpack the same thing in the second? > > I'm not sure what you expect it to unpack. Its already a variable > pointing at a tuple without the *. What do you expect the * to do? Well, it could unpack the values of the right and re-pack them on the left, except that would be a waste of time and effort :-) -- Steve From ben+python at benfinney.id.au Sun Apr 26 14:07:15 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Sun, 26 Apr 2015 22:07:15 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest_mode=E2=80=9D_be?= =?utf-8?q?fore_participating?= References: <85lhhfk8f9.fsf_-_@benfinney.id.au> Message-ID: <85h9s3jdos.fsf@benfinney.id.au> Jim Mooney writes: > On 25 April 2015 at 18:03, Ben Finney wrote: > > > Digest mode should only ever be used if you know for certain you will > > never be responding to any message. > > That brings up a great shortcut if you use gmail. If you select some > text before reply that's All that is sent. That doesn't reply to the original message. So it lacks the threading provided by the ?In-Reply-To? field, since you're not replying to the original message. It also lacks the correct Subject field, the correct attribution line, etc. So, no, I still recommend strongly against responding to digest messages ? the information simply isn't there to compose a correct reply message. Instead, disable digest mode, and only after individual messages start arriving at your mailbox can you participate properly, by replying to them. -- \ ?But it is permissible to make a judgment after you have | `\ examined the evidence. In some circles it is even encouraged.? | _o__) ?Carl Sagan, _The Burden of Skepticism_, 1987 | Ben Finney From alan.gauld at btinternet.com Sun Apr 26 14:11:20 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Sun, 26 Apr 2015 13:11:20 +0100 Subject: [Tutor] Python tkinter. Opening another script from main window stop main window from functioning. Looking for Help In-Reply-To: References: Message-ID: On 26/04/15 04:23, Spencer For Friends wrote: > I'm using a tkinter window with a button on it to open another Python > script. When the button is clicked and the new script loads it opens up > it's own window over top of my tkinter window. The problem is, when I > switch back to my tkinter window, none of the buttons are click-able > anymore. The whole windows is unresponsive. Steven has explained that this is due to using execfile(). You should virtually never use execfile(). There is nearly always a better way of doing whatever you want to do. Since in this case the second script seems to be a Tkinter program in its own right, it probably has functions that you can call from your code if you import it as a module. You might be able to create a new TopLevel window and in itys constructor call those functions or set them up as callbacks on your window. That would be the normal procedure from a GUI. If you can't do that because the other script is badly written (or if it were not a Python script) then you would be better launching it as a separate process using the subprocess module. Without knowing more about the exact structure of your code and what you are trying to do we can't really say more than that. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Sun Apr 26 21:20:40 2015 From: davea at davea.name (Dave Angel) Date: Sun, 26 Apr 2015 15:20:40 -0400 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest_mode=E2=80=9D_be?= =?utf-8?q?fore_participating?= In-Reply-To: <85h9s3jdos.fsf@benfinney.id.au> References: <85lhhfk8f9.fsf_-_@benfinney.id.au> <85h9s3jdos.fsf@benfinney.id.au> Message-ID: <553D3A88.2070303@davea.name> On 04/26/2015 08:07 AM, Ben Finney wrote: > Jim Mooney writes: > >> On 25 April 2015 at 18:03, Ben Finney wrote: >> >>> Digest mode should only ever be used if you know for certain you will >>> never be responding to any message. >> >> That brings up a great shortcut if you use gmail. If you select some >> text before reply that's All that is sent. > > That doesn't reply to the original message. So it lacks the threading > provided by the ?In-Reply-To? field, since you're not replying to the > original message. > > It also lacks the correct Subject field, the correct attribution line, > etc. So, no, I still recommend strongly against responding to digest > messages ? the information simply isn't there to compose a correct reply > message. > > Instead, disable digest mode, and only after individual messages start > arriving at your mailbox can you participate properly, by replying to > them. > When I used to subscribe here using digest, and reading with Thunderbird, I'd see each message as an attachment. To reply to one, I first opened the appropriate attachment, and did a Reply-List to it. WOrked well. I took a quick look, for another forum which I monitor using the digest, and it looks like the same approach would still work. For occasional posting. -- DaveA From cs at zip.com.au Sun Apr 26 23:15:07 2015 From: cs at zip.com.au (Cameron Simpson) Date: Mon, 27 Apr 2015 07:15:07 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest_mode=E2=80=9D_be?= =?utf-8?q?fore_participating?= In-Reply-To: <553D3A88.2070303@davea.name> References: <553D3A88.2070303@davea.name> Message-ID: <20150426211507.GA1117@cskk.homeip.net> On 26Apr2015 15:20, Dave Angel wrote: >On 04/26/2015 08:07 AM, Ben Finney wrote: >>That doesn't reply to the original message. So it lacks the threading >>provided by the ?In-Reply-To? field, since you're not replying to the >>original message. [...] > >When I used to subscribe here using digest, and reading with >Thunderbird, I'd see each message as an attachment. To reply to one, >I first opened the appropriate attachment, and did a Reply-List to it. >WOrked well. > >I took a quick look, for another forum which I monitor using the >digest, and it looks like the same approach would still work. For >occasional posting. Did you check the digest for Mesaage-ID headers for each message item? Most digests lack them and as such, replies cannot be stitched together correctly. You may have been using a mailer with a "group messages by subject" (mis?)feature, which may have merely made it look like it worked well. Cheers, Cameron Simpson I swear to god, officer, I'm fixing this bridge. Just go divert traffic. From cs at zip.com.au Sun Apr 26 23:10:54 2015 From: cs at zip.com.au (Cameron Simpson) Date: Mon, 27 Apr 2015 07:10:54 +1000 Subject: [Tutor] =?utf-8?q?Please_disable_=E2=80=9Cdigest_mode=E2=80=9D_be?= =?utf-8?q?fore_participating?= In-Reply-To: <85h9s3jdos.fsf@benfinney.id.au> References: <85h9s3jdos.fsf@benfinney.id.au> Message-ID: <20150426211054.GA83437@cskk.homeip.net> On 26Apr2015 22:07, Ben Finney wrote: >Jim Mooney writes: >> On 25 April 2015 at 18:03, Ben Finney wrote: >> > Digest mode should only ever be used if you know for certain you will >> > never be responding to any message. >> >> That brings up a great shortcut if you use gmail. If you select some >> text before reply that's All that is sent. > >That doesn't reply to the original message. So it lacks the threading >provided by the ?In-Reply-To? field, since you're not replying to the >original message. >It also lacks [...] Yes, but it _does_ point an easy way for people from top-posting do-not-trim-quotes cultures to adopt the technophile's trim-quotes-for-relevance style which is so useful in discussion (versus chatter). Apple Mail also supports this handy "use the selected text for the context quote" technique and I think a number of the other OSX based mail programs. It doesn't cut it for multipoint quote1-reply1 quote2-reply2 messages, but it is a great jumping off point for people new to the method. _If_ the OP has abandoned digest mode, Jim's pointer is very useful. Before then I agree that it is far less so, but that is because digests are very unfortunate. Cheers, Cameron Simpson Never belong to any party, always oppose privileged classes and public plunderers, never lack sympathy with the poor, always remain devoted to the public welfare, never be satisfied with merely printing news, always be drastically independent, never be afraid to attack wrong, whether by predatory plutocracy or predatory poverty. - Joseph Pulitzer, 1907 Speech From cybervigilante at gmail.com Mon Apr 27 01:23:21 2015 From: cybervigilante at gmail.com (Jim Mooney Py3winXP) Date: Sun, 26 Apr 2015 16:23:21 -0700 Subject: [Tutor] output is all integer when there should be some floats In-Reply-To: <20150426110256.GK5663@ando.pearwood.info> References: <20150426110256.GK5663@ando.pearwood.info> Message-ID: On 26 April 2015 at 04:02, Steven D'Aprano wrote: > for kind in (int, float): > try: > return kind(astring) > That puzzled me for a moment until I remembered you can toss functions around in Python. Something to play with on a Sunday afternoon ;') But aren't most languages going in that direction? (Well, maybe not COBOL) -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From alexgonzi0204 at gmail.com Mon Apr 27 03:18:04 2015 From: alexgonzi0204 at gmail.com (alex gonsalez) Date: Sun, 26 Apr 2015 21:18:04 -0400 Subject: [Tutor] CPU Scheduling Message-ID: Need help trying to implement a CPU scheduling algorithm.I am not even sure where to start on this. Can someone please guide me and walk me through the steps for this? Assignment: The Simulation. Simulating the scheduling of a single CPU is a type of discrete event simulation in which you iterate over discrete steps of time and handle events as they occur. The simulation continues for a given amount of time or until all data has been processed. Add the processes to the ready queue. cpu = None curTime = 0 while ready queue is not empty : handle events that occur during the current time step curTime = curTime + 1 For this project, the simulation will continue while there are still processes that need to use the CPU. There are three types of events that can occur: the CPU is initially empty, the time slice for the current process on the CPU has expired or the process has completed execution before the time slice has expired. ? If the CPU is initially empty, select the next process from the ready queue and assign it to the CPU. 1 CS 112 ? Spring 2015 Programming Assignment Four ? 2 ? If a process completes execution, it?s removed from the system and it?s total wait time is added to a running total. ? If a process has used its time slice, the process is removed from the CPU and the next process is selected from the ready queue and assigned to the CPU. The process that was removed is added back to the ready queue to wait its turn before it can again use the CPU. Note that the next process has to be dequeued before the current process is added back to the queue. Text File. The simulation data will be contained in a text file that has the following format: 2 15 8 35 0 25 10 5 5 5 2 7 12 30 7 10 0 3 8 15 where each line contains information for a single process. The first value is the priority and the second value is the amount of processing time required (i.e. the total amount of time the processor needs to use the CPU). Note that the lower the priority value, the higher the priority. Assume the first line contains the information for process 1, the second line for process 2, and so on. The Algorithms. You are to implement two priority based scheduling algorithms. For the first algorithm, the next process selected from the ready queue is simply the one with the highest priority. For the second algorithm, you are to make a slight modification. Each time a process is put back into the ready queue, after being removed from the CPU, reduce the priority level by 5. Results. Your program should produce output similar to the following: Number of processes: 10 Time slice: 10 Total time: 150 Algorithm 1 Avg wait time: 60.10 Algorithm 2 Avg wait time: 62.80 To compute the average wait time over all of the processes, you will need to keep track of how much time each process spends in the ready queue and then compute the average of those times. Assume that all processes are started at the exact same time. CS 112 ? Spring 2015 Programming Assignment Four ? 3 Requirements. Your program should be placed within a driver named cpu.py. Your program should be well structured and commented appropriately as indicated in the programming style guide provided on the course web page. Some important points to keep in mind: ? A linked list implementation of the Priority Queue ADT is provided in the course directory. ? You must use a top-down design with functions. ? Your program should read from the user the name of the text file that contains the simulation data and the length of a time slice (as an integer). ? Use a variable (cpu) to hold a reference to the process object (your storage object) for the process that is currently assigned to the cpu. ? In addition to the curTime variable, you should use a second time variable that indicates the time when a process needs to be switched off the cpu. This variable acts as an alarm or the time an alarm goes off to signal an event. When a process is assigned to the cpu, compute the time when it should be switched off (current time + time slice or current time + time remaining for the process). ? To compute the wait time, you will need to keep track of the current time when the process is added to the ready queue. Then each time a process is removed from the ready queue, compute how much time it spent in the queue and add that to the processes total wait time. ? You will need to use a storage object to store the information for a single process. It should contain the process number, the priority, the remaining CPU time required for that process, its total wait time, and the time it was added to the ready queue. The data in the storage object must be stored as integer values. ? Each time the process is added back to the ready queue, you should add the storage objects to the priority queue and update the remaining CPU time From alan.gauld at btinternet.com Mon Apr 27 10:03:55 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 27 Apr 2015 09:03:55 +0100 Subject: [Tutor] CPU Scheduling In-Reply-To: References: Message-ID: On 27/04/15 02:18, alex gonsalez wrote: > Need help trying to implement a CPU scheduling algorithm.I am not even sure > where to start on this. Can someone please guide me and walk me through the > steps for this? Your assignment gives a pretty thorough description of what needs to be done. Maybe you can start by drafting a pseudo code description of the main scheduling algorithm? Also you could think about the data structures you need. It mentions a linked list although in Python I'd think a normal list would do just as well. What variables are you going to need? What historic data are you going to store? And how will that be represented? It describes two separate algorithms you need to implement. Can you define those in pseudo code? > > Assignment: > The Simulation. > Simulating the scheduling of a single CPU is a type of discrete event > simulation in which you iterate over discrete steps of time and handle > events as they occur. The simulation continues for a given amount of time > or until all data has been processed.... -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From gebrekirstos2015 at gmail.com Mon Apr 27 11:32:16 2015 From: gebrekirstos2015 at gmail.com (Gebrekirstos G/meskel) Date: Mon, 27 Apr 2015 12:32:16 +0300 Subject: [Tutor] plz help me Message-ID: Hi guys: I need help for consume .NET web service in python code from Ubuntu OS thanks alot G/kirstos From wombingsac at gmail.com Mon Apr 27 12:37:54 2015 From: wombingsac at gmail.com (Whom Isac) Date: Mon, 27 Apr 2015 20:37:54 +1000 Subject: [Tutor] Adding consecutive numbers Message-ID: Hi, I am trying to build a python mini program to solve a math problem . I wanted my program to ask two number from the operator and it can add those number as a integer but as consecutive number in range. For example, if num1 entry =1 & num2 entry = 100 , the program should be adding number from 1 to 100 together(which should equal to 5050). I thought that I could use range() to use it for any given input from the user. However, there are few argumentation error and I don't know why my bool function did not work in while loop. Is there any way to make the program more concise. I have uploaded my code file below. Please, note that I am fairly new to programming and donot use complex modules, therefore, suggest me where I was wrong with the code. I have checked for indentation error, however, there were no error. So, I don't have any idea about the error. Thanks. -------------- next part -------------- ##Goal: Building a math program, which allows addition of two numbers in range in consequitive ## sequence e.g. 1+2...+n if __name__=='__main__': interact() def iteract(): print('''Welcome to My new Math program!! With this program, you can find the sum of any consequitive numbers.''') print('So Just add your numbers in following spaces') x =int(input('Please enter your first number: ')) y =int(input('Please enter your second number: ')) while True: if x References: Message-ID: On 27/04/15 10:32, Gebrekirstos G/meskel wrote: > Hi guys: > > I need help for > > consume .NET web service in python code from Ubuntu OS OK, But to help you we need you to help us. What does this web service look like? What version of Python are you using? What have tyou tried so far , if anything? What experience of programming 9ion Python) do you have? Web services come in all kinds of shapes and sizes from XMLRPC to SOAP to RESTful services. give us a clue. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Mon Apr 27 14:16:14 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 27 Apr 2015 13:16:14 +0100 Subject: [Tutor] Adding consecutive numbers In-Reply-To: References: Message-ID: On 27/04/15 11:37, Whom Isac wrote: > num1 entry =1 & num2 entry = 100 , the program should be adding number from > 1 to 100 together(which should equal to 5050). > I have uploaded my code file below. Infortunately we can't see it. Since it is presumably quite short please just send it in the body of your email. Also include the full error text that you refer to, Also tell us the Python version and OS you are using. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Mon Apr 27 14:41:58 2015 From: davea at davea.name (Dave Angel) Date: Mon, 27 Apr 2015 08:41:58 -0400 Subject: [Tutor] Adding consecutive numbers In-Reply-To: References: Message-ID: <553E2E96.3000509@davea.name> On 04/27/2015 06:37 AM, Whom Isac wrote: > Hi, I am trying to build a python mini program to solve a math problem . I > wanted my program to ask two number from the operator and it can add those > number as a integer but as consecutive number in range. For example, if > num1 entry =1 & num2 entry = 100 , the program should be adding number from > 1 to 100 together(which should equal to 5050). I thought that I could use > range() to use it for any given input from the user. However, there are few > argumentation error and I don't know why my bool function did not work in > while loop. Is there any way to make the program more concise. > I have uploaded my code file below. Please, note that I am fairly new to > programming and donot use complex modules, therefore, suggest me where I > was wrong with the code. I have checked for indentation error, however, > there were no error. So, I don't have any idea about the error. > Thanks. > You really shouldn't use attachments on this list, since many cannot see them. I happen to be able to, so I'll try to comment. In addition, each time you start a new thread, you should specify what Python version you're trying to use, and what OS. I never heard of an "argumentation error" so you'll really have to show the exact error. Just copy/paste it from your user shell. And exact for syntax errors, show the complete traceback. Your code has many errors in it, and is unnecessarily complex. At its simplest, you could use some simple algebra, and write: x =int(input('Please enter your first number: ')) y =int(input('Please enter your second number: ')) print (x+y) * (y-x + 1) / 2 But if you really have to do the sum, then you need to build a list, and sum it. That's not very hard either, since range() returns a list, and the sum() function is built-in. But now, let's look at your code, and identify a few of the problems with it. Your second line calls function interact(), which isn't defined yet. And in fact, when it is defined, it is spelled differently. Put your top-level code (those two lines, anyway) at the *end* of the file, after the function(s) it needs are defined. In function iteract (spelled inconsistently), you have a while True loop, with a break in the else clause. But if x=y, you'll hit the break without defining z, so print z will throw an exception. Also in that function you call a function called adding_sum_in(), but there's no function by that name. In function find_range(), the first thing you do is trash your arguments. So whatever else is in that function probably doesn't matter much. In the loop: for num in x: x.append(num) you're modifying the same thing you're looping over. Not generally a good idea, so I have no idea if it'll do anything useful or not. Probably not. return R = range({0},{1}).format(x,y) is a syntax error. def adding_sum_in_range(x, y): c= find_range(x,y) Total_sum = 0 for i in c: Total_sum += i return Total_sum You have an indentation problem there, as this will return the first time through the loop. def addition(x, y): num1=(x) num2=(y) return num1+num2 Another indentation problem. -- DaveA From breamoreboy at yahoo.co.uk Mon Apr 27 14:58:51 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Mon, 27 Apr 2015 13:58:51 +0100 Subject: [Tutor] Adding consecutive numbers In-Reply-To: <553E2E96.3000509@davea.name> References: <553E2E96.3000509@davea.name> Message-ID: On 27/04/2015 13:41, Dave Angel wrote: > On 04/27/2015 06:37 AM, Whom Isac wrote: > > But if you really have to do the sum, then you need to build a list, and > sum it. That's not very hard either, since range() returns a list, and > the sum() function is built-in. > range() only returns a list in Python 2 but it doesn't matter here as sum() accepts any iterable, not just a list. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From steve at pearwood.info Mon Apr 27 15:45:10 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 27 Apr 2015 23:45:10 +1000 Subject: [Tutor] Adding consecutive numbers In-Reply-To: References: Message-ID: <20150427134510.GP5663@ando.pearwood.info> Hi, and welcome! My answers are below. On Mon, Apr 27, 2015 at 08:37:54PM +1000, Whom Isac wrote: > Hi, I am trying to build a python mini program to solve a math problem . I > wanted my program to ask two number from the operator and it can add those > number as a integer but as consecutive number in range. For example, if > num1 entry =1 & num2 entry = 100 , the program should be adding number from > 1 to 100 together(which should equal to 5050). I thought that I could use > range() to use it for any given input from the user. However, there are few > argumentation error and I don't know why my bool function did not work in > while loop. Is there any way to make the program more concise. > I have uploaded my code file below. Please, note that I am fairly new to > programming and donot use complex modules, therefore, suggest me where I > was wrong with the code. I have checked for indentation error, however, > there were no error. So, I don't have any idea about the error. > Thanks. Thank you very much for sending the code you have so far! Unfortunately, I wish I had good news but I don't -- nearly everything about it is wrong. You have a good idea of what you want the program to do, and you have made a good attempt at splitting it into separate functions, but sadly the details are wrong and that prevents your code from working. Let's see if we can fix that. The first, and most important, thing is that Python can only run code it has already seen. So if I write this: do_something() # Call the function. def do_something(): # Define the function. print("Working really hard...") it will fail because at the time Python tries to call do_something() it doesn't exist yet. This is your very first problem: > if __name__=='__main__': > interact() > > def iteract(): When you try to call interact(), the function doesn't exist! Rule 1: Put your function definitions at the top of the file. Put the if __name__ == '__main__' block at the bottom of the file. That way, by the time Python reaches that block and calls the functions, they will have already been created and are ready to use. Now, let's think about good program design. A well-designed program will separate the program logic from the user-interface. In other words, the part of the program which calculates the result should be kept apart from the part of the program which communicates with the user. That makes it much easier to test each half separately, in case of any problems. So, let's start with a simple function that takes two integers as arguments, and adds all the numbers between then. Python gives you the tools to make this easy: ---- cut here ----- def add_range(start, end): """Add the numbers between start and end inclusive.""" the_range = range(start, end+1) return sum(the_range) print(add_range(1, 7)) # Should print 28 print(add_range(8, 20)) # Should print 128 ---- cut here ---- There is a function, sum(), which is used for adding up a sequence of numbers, and another function, range(), which creates a sequence of numbers from start to one less than the end. So we add one more to the end, create the range, then use sum() to add up the numbers. Now let's have another function to get a number from the user. We will use that function to get the starting number, then re-use it to get the ending number, then finally pass those two number to the add_range() function we created above. ---- cut here ---- def get_user_number(message): """Get an int from the user.""" while True: # Keep trying forever. answer = input(message) if answer.isdigit(): return int(answer) else: print("Sorry, that is not a number!") start = get_user_number("Please enter your starting number: ") end = get_user_number("Please enter your ending number: ") print("start is", start, "; end is", end) print(add_range(start, end)) ---- cut here ---- And that's nearly all you need! Any questions? -- Steve From steve at pearwood.info Mon Apr 27 15:50:28 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 27 Apr 2015 23:50:28 +1000 Subject: [Tutor] plz help me In-Reply-To: References: Message-ID: <20150427135028.GQ5663@ando.pearwood.info> On Mon, Apr 27, 2015 at 12:32:16PM +0300, Gebrekirstos G/meskel wrote: > Hi guys: > > I need help for > > consume .NET web service in python code from Ubuntu OS Show us the code you have, and the error it is producing, and well try to help. -- Steve From dyoo at hashcollision.org Mon Apr 27 19:13:32 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Mon, 27 Apr 2015 10:13:32 -0700 Subject: [Tutor] CPU Scheduling In-Reply-To: References: Message-ID: > On 27/04/15 02:18, alex gonsalez wrote: >> >> Need help trying to implement a CPU scheduling algorithm. Hi Alex, Unfortunately, this is way out of scope for Python-tutor; I think you'll be better off discussing with your classmates and professor. You'll get more productive answers that way. One reason that here is probably not the right place for this question is because, essentially, you're asking a classroom full of programming beginners, many of us who are still learning how to do things like loops, variables, and values, how to do a hard-core operating system homework exercise. Another reason is that most academic institutions have an honor code which prohibits or discourages certain activities. As an example of one, see a random one, like the GMU CS honor code: http://cs.gmu.edu/wiki/pmwiki.php/HonorCode/CSHonorCodePolicies From wolfrage8765 at gmail.com Mon Apr 27 20:03:06 2015 From: wolfrage8765 at gmail.com (WolfRage) Date: Mon, 27 Apr 2015 14:03:06 -0400 Subject: [Tutor] CPU Scheduling In-Reply-To: References: Message-ID: <553E79DA.6080104@gmail.com> On 04/27/2015 01:13 PM, Danny Yoo wrote: >> On 27/04/15 02:18, alex gonsalez wrote: >>> >>> Need help trying to implement a CPU scheduling algorithm. Can I recommend that you read this: http://www.dabeaz.com/coroutines/Coroutines.pdf About half way through it has a Excellent example of how an OS schedules processes. From dfarooqi at lakeheadu.ca Mon Apr 27 20:10:15 2015 From: dfarooqi at lakeheadu.ca (Durrayshehwar Farooqi) Date: Mon, 27 Apr 2015 14:10:15 -0400 Subject: [Tutor] MTIE calculation Message-ID: Hello, Need help with how to calculate MTIE using Python. I have imported numpy and allantools, please help. Thanks -- Kind Regards; *Durray * From alan.gauld at btinternet.com Mon Apr 27 20:36:32 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Mon, 27 Apr 2015 19:36:32 +0100 Subject: [Tutor] MTIE calculation In-Reply-To: References: Message-ID: On 27/04/15 19:10, Durrayshehwar Farooqi wrote: > Need help with how to calculate MTIE using Python. I have imported numpy > and allantools, please help. You probably need to tell us exactly what MTIE is and how it works. You also need to tell us which Python version, which OS and show us any code you have written already. This list is for people learning Python and its standard library, don't assume we know anything about your particular area of study. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From oscar.j.benjamin at gmail.com Tue Apr 28 01:19:26 2015 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Tue, 28 Apr 2015 00:19:26 +0100 Subject: [Tutor] Python tkinter. Opening another script from main window stop main window from functioning. Looking for Help In-Reply-To: References: Message-ID: On 26 April 2015 at 04:23, Spencer For Friends wrote: > Hi all. I'm new to Python and I'm trying my best to learn, but I'm really > struggling with some problems. > > I'm using a tkinter window with a button on it to open another Python > script. When the button is clicked and the new script loads it opens up > it's own window over top of my tkinter window. The problem is, when I > switch back to my tkinter window, none of the buttons are click-able > anymore. The whole windows is unresponsive. The click animation on the > button doesn't even function. Any help to resolve this would be greatly > appreciated. Here is my code. Hi Spencer, The problem is that you're trying to run a long running task within your applications event loop. You have to understand that the main loop in a GUI program looks something like this: while True: event = get_event_from_queue() if event == button_pressed: call_button_callback() elif event == key_pressed: respond_to_keypress() elif event == close_button_clicked: close_windows() break # etc. Your callback function takes a long time to run and during that time the event loop is still waiting for call_button_callback() to finish. The result is that it doesn't respond to anything during that time. You can test the same effect with a simpler program: from Tkinter import Tk, Button, S from tkMessageBox import showinfo def callback(): total = sum(1 for _ in xrange(10**8)) # <-- slow showinfo(str(total)) root = Tk() button1 = Button(text='Click me', command=callback) button1.config(height=3, width=25) button1.grid(row=1, column=0, sticky=S) root.mainloop() When you run this program and click the button it will freeze for 5-10 seconds while running the slow callback() function. If you click something during this time then your click will go into the event queue. The event loop will retrieve that click message once it has finished waiting for the callback function to finish. You can test this by clicking the 'Click me' button and then clicking the close button before it has finished. As soon as the callback finishes the program will close. The solution to this is to use threads or subprocesses. On the face of it this is quite simple but actually writing multi-threaded code is quite tricky. Here's how to modify the above program to run the slow callback function in a thread: from Tkinter import Tk, Button, S from tkMessageBox import showinfo from threading import Thread def callback_threaded(): Thread(target=callback).start() def callback(): total = sum(1 for _ in xrange(10**8)) # <-- slow showinfo(str(total)) root = Tk() button1 = Button(text='Click me', command=callback_threaded) button1.config(height=3, width=25) button1.grid(row=1, column=0, sticky=S) root.mainloop() This program will create a separate execution thread to run the callback. It's quite simple if you just want to run execfile in parallel with your GUI. Where it gets trickier is if you need the threads to interact and you need to pass data between them. -- Oscar From jon.engle at gmail.com Tue Apr 28 04:14:06 2015 From: jon.engle at gmail.com (Juanald Reagan) Date: Mon, 27 Apr 2015 22:14:06 -0400 Subject: [Tutor] pip install M2crypto Message-ID: Good Evening, I am trying to install the M2crypto package via pip and receive an error. Python version is 2.7.4, any ideas on how to fix the SWIG error? Jon$ sudo -H pip install M2crypto /Library/Python/2.7/site-packages/pip-6.1.1-py2.7.egg/pip/_vendor/requests/packages/urllib3/util/ssl_.py:79: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning . InsecurePlatformWarning Collecting M2crypto /Library/Python/2.7/site-packages/pip-6.1.1-py2.7.egg/pip/_vendor/requests/packages/urllib3/util/ssl_.py:79: InsecurePlatformWarning: A true SSLContext object is not available. This prevents urllib3 from configuring SSL appropriately and may cause certain SSL connections to fail. For more information, see https://urllib3.readthedocs.org/en/latest/security.html#insecureplatformwarning . InsecurePlatformWarning Downloading M2Crypto-0.22.3.tar.gz (74kB) 100% |????????????????????????????????| 77kB 784kB/s Installing collected packages: M2crypto Running setup.py install for M2crypto Complete output from command /usr/bin/python -c "import setuptools, tokenize;__file__='/private/tmp/pip-build-covxwD/M2crypto/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-NWsSZ5-record/install-record.txt --single-version-externally-managed --compile: running install running build running build_py creating build creating build/lib.macosx-10.10-intel-2.7 creating build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/__init__.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/ASN1.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/AuthCookie.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/BIO.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/BN.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/callback.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/DH.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/DSA.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/EC.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/Engine.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/Err.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/EVP.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/ftpslib.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/httpslib.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/m2.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/m2urllib.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/m2urllib2.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/m2xmlrpclib.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/Rand.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/RC4.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/RSA.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/SMIME.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/threading.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/util.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto copying M2Crypto/X509.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto creating build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/__init__.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/cb.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/Checker.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/Cipher.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/Connection.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/Context.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/Session.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/ssl_dispatcher.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/SSLServer.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/timeout.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL copying M2Crypto/SSL/TwistedProtocolWrapper.py -> build/lib.macosx-10.10-intel-2.7/M2Crypto/SSL running build_ext building 'M2Crypto.__m2crypto' extension swigging SWIG/_m2crypto.i to SWIG/_m2crypto_wrap.c swig -python -I/System/Library/Frameworks/Python.framework/Versions/2.7/include/python2.7 -I/usr/include -I/usr/include/openssl -includeall -modern -o SWIG/_m2crypto_wrap.c SWIG/_m2crypto.i unable to execute swig: No such file or directory error: command 'swig' failed with exit status 1 ---------------------------------------- Command "/usr/bin/python -c "import setuptools, tokenize;__file__='/private/tmp/pip-build-covxwD/M2crypto/setup.py';exec(compile(getattr(tokenize, 'open', open)(__file__).read().replace('\r\n', '\n'), __file__, 'exec'))" install --record /tmp/pip-NWsSZ5-record/install-record.txt --single-version-externally-managed --compile" failed with error code 1 in /private/tmp/pip-build-covxwD/M2crypto -- Cheers, Jon From mitesh.budhabhatti at gmail.com Tue Apr 28 09:31:04 2015 From: mitesh.budhabhatti at gmail.com (Mitesh H. Budhabhatti) Date: Tue, 28 Apr 2015 13:01:04 +0530 Subject: [Tutor] Naming conventions Message-ID: Hello Friends, Can you please suggest good naming conventions/guidelines to following while writing Python code? Thanks. From ctoshea1024 at email.campbell.edu Tue Apr 28 01:08:06 2015 From: ctoshea1024 at email.campbell.edu (O'Shea, Connor) Date: Mon, 27 Apr 2015 19:08:06 -0400 Subject: [Tutor] Trouble Downloading 3.2 tutorial Message-ID: Greetings. I have been experiencing difficulty getting my computer to download the 3.2 python program. My computer has Windows 8 software. What do you suggest I do to address this problem? From breamoreboy at yahoo.co.uk Tue Apr 28 09:38:32 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Tue, 28 Apr 2015 08:38:32 +0100 Subject: [Tutor] Naming conventions In-Reply-To: References: Message-ID: On 28/04/2015 08:31, Mitesh H. Budhabhatti wrote: > Hello Friends, > > Can you please suggest good naming conventions/guidelines to following > while writing Python code? Thanks. > PEP 8 - Style Guide for Python Code at https://www.python.org/dev/peps/pep-0008/ -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From alan.gauld at btinternet.com Tue Apr 28 09:51:52 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 28 Apr 2015 08:51:52 +0100 Subject: [Tutor] Trouble Downloading 3.2 tutorial In-Reply-To: References: Message-ID: On 28/04/15 00:08, O'Shea, Connor wrote: > Greetings. I have been experiencing difficulty getting my computer to > download the 3.2 python program. My computer has Windows 8 software. What > do you suggest I do to address this problem? You don't say what kind of "trouble" nor which distribution of Python you are trying to download. If its the official python.org one then, as a Windows user I suggest you try the ActiveState site since their version includes many extra Windows features. Also you say Python v3.2 however the latest version is v3.4. Unless you have a strong reason to use 3.2 I suggest you get 3.4 instead, any 3.2 code should run under 3.4. If you are trying to download one of the "super Pythons" like Anaconda then I can't help and suggest you ask on their user fora. If none of that helps come back to us with a more detailed description of exactly what you are trying to do, where, what happens, and any error messages you see. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Tue Apr 28 09:54:45 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 28 Apr 2015 08:54:45 +0100 Subject: [Tutor] pip install M2crypto In-Reply-To: References: Message-ID: On 28/04/15 03:14, Juanald Reagan wrote: > Good Evening, > > I am trying to install the M2crypto package via pip and receive an error. > Python version is 2.7.4, any ideas on how to fix the SWIG error? Do you have SWIG installed? It should be in your repo. > > unable to execute swig: No such file or directory > > error: command 'swig' failed with exit status 1 -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From paradox at pobox.com Tue Apr 28 10:51:57 2015 From: paradox at pobox.com (Paradox) Date: Tue, 28 Apr 2015 16:51:57 +0800 Subject: [Tutor] How to output dictionary data to CSV file Message-ID: <553F4A2D.8030500@pobox.com> I have some data structured like this: {'B002':'NRP 2014','B003':'HBB 2015'} Basically account numbers and project names, each account number has a project name. I represent it in a dictionary because that seemed the best way to keep the account numbers and project names together. I want to save that information to a file, CSV seemed the easiest format (though I am open to suggestions if there is a better way!). I expected I could write a function that would create a CSV file that looks like this: B002,NRP 2014 B003,HBB 2015 I thought the DictWriter method of the CSV module should do the trick so wrote this: def write_fqas(fqa_csv,fqa_dict): with open('fqa_csv','w') as csvfile: writer = csv.DictWriter(csvfile,fieldnames=['FQA','Description'] writer.writerows(fqa_dict) This didn't yield the results I was looking for, instead it raises ValueError: dict contains fields not in fieldnames: 'B', '0', '0', '2' It seems to be parsing through the key of the first item in the dictionary rather than simply saving it to the CSV file as the first field on a line (like I expected). Obviously there is something about how csv.DictWriter works that I don't understand. Any assistance is appreciated. thomas ============================== Thomas C. Hicks, MD, MPH Training Manager, Gansu Gateway Lanzhou, Gansu, PR China From paradox at pobox.com Tue Apr 28 11:00:34 2015 From: paradox at pobox.com (Paradox) Date: Tue, 28 Apr 2015 17:00:34 +0800 Subject: [Tutor] How to output dictionary data to CSV file In-Reply-To: <553F4A2D.8030500@pobox.com> References: <553F4A2D.8030500@pobox.com> Message-ID: <553F4C32.8000002@pobox.com> How rude of me, I neglected to note I am using Python 3.4.3. On 04/28/2015 04:51 PM, Paradox wrote: > I have some data structured like this: > > {'B002':'NRP 2014','B003':'HBB 2015'} > > Basically account numbers and project names, each account number has a > project name. I represent it in a dictionary because that seemed the > best way to keep the account numbers and project names together. I > want to save that information to a file, CSV seemed the easiest format > (though I am open to suggestions if there is a better way!). I > expected I could write a function that would create a CSV file that > looks like this: > > B002,NRP 2014 > B003,HBB 2015 > > I thought the DictWriter method of the CSV module should do the trick > so wrote this: > > def write_fqas(fqa_csv,fqa_dict): > with open('fqa_csv','w') as csvfile: > writer = csv.DictWriter(csvfile,fieldnames=['FQA','Description'] > writer.writerows(fqa_dict) > > This didn't yield the results I was looking for, instead it raises > > ValueError: dict contains fields not in fieldnames: 'B', '0', '0', '2' > > It seems to be parsing through the key of the first item in the > dictionary rather than simply saving it to the CSV file as the first > field on a line (like I expected). Obviously there is something about > how csv.DictWriter works that I don't understand. > > Any assistance is appreciated. > > thomas > ============================== > Thomas C. Hicks, MD, MPH > Training Manager, Gansu Gateway > Lanzhou, Gansu, PR China From __peter__ at web.de Tue Apr 28 11:30:54 2015 From: __peter__ at web.de (Peter Otten) Date: Tue, 28 Apr 2015 11:30:54 +0200 Subject: [Tutor] How to output dictionary data to CSV file References: <553F4A2D.8030500@pobox.com> Message-ID: Paradox wrote: > I have some data structured like this: > > {'B002':'NRP 2014','B003':'HBB 2015'} > > Basically account numbers and project names, each account number has a > project name. I represent it in a dictionary because that seemed the > best way to keep the account numbers and project names together. I want > to save that information to a file, CSV seemed the easiest format > (though I am open to suggestions if there is a better way!). I expected > I could write a function that would create a CSV file that looks like > this: > > B002,NRP 2014 > B003,HBB 2015 > > I thought the DictWriter method of the CSV module should do the trick so > wrote this: > > def write_fqas(fqa_csv,fqa_dict): > with open('fqa_csv','w') as csvfile: > writer = csv.DictWriter(csvfile,fieldnames=['FQA','Description'] > writer.writerows(fqa_dict) > > This didn't yield the results I was looking for, instead it raises > > ValueError: dict contains fields not in fieldnames: 'B', '0', '0', '2' > > It seems to be parsing through the key of the first item in the > dictionary rather than simply saving it to the CSV file as the first > field on a line (like I expected). Obviously there is something about > how csv.DictWriter works that I don't understand. DictWriter expects a sequence of dicts where the keys are the column names. Example: >>> import csv >>> import sys >>> data = [ ... {"FQA": "B002", "Description": "NRP 2014"}, ... {"FQA": "B003", "Description": "HBB 2015"}, ... ] >>> writer = csv.DictWriter(sys.stdout, fieldnames=["FQA", "Description"]) >>> writer.writerows(data) B002,NRP 2014 B003,HBB 2015 As you want to write both keys and values as a column you can pass the dict items() to a normal csv.writer: >>> data = {'B002':'NRP 2014','B003':'HBB 2015'} >>> writer = csv.writer(sys.stdout) >>> writer.writerows(data.items()) B002,NRP 2014 B003,HBB 2015 > How rude of me, I neglected to note I am using Python 3.4.3. And now you're top-posting to make it even worse ;) From paradox at pobox.com Tue Apr 28 12:07:17 2015 From: paradox at pobox.com (Thomas C. Hicks) Date: Tue, 28 Apr 2015 18:07:17 +0800 Subject: [Tutor] How to output dictionary data to CSV file :p: In-Reply-To: References: <553F4A2D.8030500@pobox.com> Message-ID: <553F5BD5.2000704@pobox.com> On 04/28/2015 05:30 PM, Peter Otten wrote: >>>> >>>data = {'B002':'NRP 2014','B003':'HBB 2015'} >>>> >>>writer = csv.writer(sys.stdout) >>>> >>>writer.writerows(data.items()) > B002,NRP 2014 > B003,HBB 2015 That is exactly what I was looking for! Thanks, apparently my knowledge deficit is in understanding dictionary methods. > >> >How rude of me, I neglected to note I am using Python 3.4.3. > And now you're top-posting to make it even worse;) Lesson learned! thomas From alan.gauld at btinternet.com Tue Apr 28 15:43:09 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 28 Apr 2015 14:43:09 +0100 Subject: [Tutor] How to output dictionary data to CSV file In-Reply-To: <553F4A2D.8030500@pobox.com> References: <553F4A2D.8030500@pobox.com> Message-ID: On 28/04/15 09:51, Paradox wrote: > to save that information to a file, CSV seemed the easiest format You could consider JSON too. JSON looks a lot like a Python dictionary of strings so is almost a perfect match to your data. The json module is in the standard library. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From sage at cyberguerrilla.org Tue Apr 28 11:55:46 2015 From: sage at cyberguerrilla.org (Sage Hack) Date: Tue, 28 Apr 2015 05:55:46 -0400 Subject: [Tutor] Pythonic review (descriptors) Message-ID: <553F5922.1040701@cyberguerrilla.org> I'm looking for somebody willing to review parts of this code https://github.com/SageHack/cloud-buster and let me know what is not Pythonic :P I want to improve my Python coding skills but I'm not sure exactly what to study next. Right now I'm trying to use descriptors correctly and I'd like to know if this is about right https://github.com/SageHack/cloud-buster/tree/master/bust/descriptor Thanks :) From alan.gauld at btinternet.com Tue Apr 28 16:21:44 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 28 Apr 2015 15:21:44 +0100 Subject: [Tutor] Pythonic review (descriptors) In-Reply-To: <553F5922.1040701@cyberguerrilla.org> References: <553F5922.1040701@cyberguerrilla.org> Message-ID: On 28/04/15 10:55, Sage Hack wrote: > I'm looking for somebody willing to review parts of this code > https://github.com/SageHack/cloud-buster and let me know what is not > Pythonic :P > https://github.com/SageHack/cloud-buster/tree/master/bust/descriptor The thing that jumps out to me is your use of class variables to hold a dictionary of instance responses based on the instance ID. That pattern looks like this, and you use it in every class: class SomeClass: classvar = {} def __init__(self,id): self.id = id def __get__(self...): v = getSomeValue() sel.classvar[self.id] = v Normally you'd store instance specific data in the instance itself not in a class variable. also you overwrite the classvariable entry for each instance every time you call the get(). Is that really what you want? The other thing is that you should have docstrings for both the classes and methods. Finally, and not Python specific, You have several classes sharing the same 'ID' data - self.domain - that's usually a bad OOP smell. Only one class should be mastering any given type of data, so maybe your other classes are really methods of whichever is the master class? Particularly since they don't have any explicit methods (also a bad OOP smell) of their own. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Tue Apr 28 16:27:39 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 28 Apr 2015 15:27:39 +0100 Subject: [Tutor] Pythonic review (descriptors) In-Reply-To: <553F5922.1040701@cyberguerrilla.org> References: <553F5922.1040701@cyberguerrilla.org> Message-ID: On 28/04/15 10:55, Sage Hack wrote: > I'm looking for somebody willing to review parts of this code > https://github.com/SageHack/cloud-buster and let me know what is not > Pythonic :P > https://github.com/SageHack/cloud-buster/tree/master/bust/descriptor Another point re the PageTitle class: class PageTitle(object): titles = {} def __init__(self, url, host=None): self.url = url self.host = host def __get__(self, obj=None, objtype=None):... @property def id(self): if self.host: return self.url+':'+self.host else: return self.url There is not much point in calculating the id each time, it could simply be set in the init(). You never change the url or host. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From steve at pearwood.info Tue Apr 28 17:15:19 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 29 Apr 2015 01:15:19 +1000 Subject: [Tutor] Naming conventions In-Reply-To: References: Message-ID: <20150428151518.GV5663@ando.pearwood.info> On Tue, Apr 28, 2015 at 01:01:04PM +0530, Mitesh H. Budhabhatti wrote: > Hello Friends, > > Can you please suggest good naming conventions/guidelines to following > while writing Python code? Thanks. Most important rule of all: names should be descriptive and understandable, not too short or cryptic, not so long that they are painful to use. Very common names may be abbreviated. Names should be easy to say aloud. # Good names length, len, map, format # Bad names a, the_thing_we_process, szty Avoid "funny" or meaningless names: pizza = 23 homework = 5 print (pizza > homework) It is acceptable to use standard one-letter variable names in generic functions, especially for algebraic (maths) functions and short utility functions, e.g.: i, j, k: integer loop variables m, n: other integers x, y: floats z: complex numbers s: string or set d: dict L: list (don't use l because it can look like 1) o: object u, v: vectors, arrays, sets are common choices. But don't over-use one-letter names. Otherwise, names should be self-descriptive: # Bad L = get_customers() # list of customers # Good customers = get_customers() Use plurals for lists, sets or dicts of some data type, and the singular for individual data types. E.g.: names = ['John', 'Mary', 'Fred', 'Sue'] for name in names: process(name) Functions and methods should be verbs or verb-phrases in all lowercase, for example: expand() sort() lift() prepare_database() create_factory() Variables holding data values should be nouns: page count header footer server client factory (Watch out for words which can be both a noun and a verb, like count.) Classes should be nouns with initial capitals: Car Engine Animal HTTPServer and instances should be lowercase: server = HTTPServer() The exception is if the class is a "small" primitive or simple type, like built-ins int, str, dict, list etc. But even then, you may choose to use Initial Capitals instead. Modules should follow the all-lowercase name. If possible, modules should describe what they are about: math string io unicodedata but it is also acceptable for modules to have an arbitrary name which you just have to learn: pillow flask zope fabric nose Does this help? -- Steve From diliupg at gmail.com Tue Apr 28 17:38:46 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Tue, 28 Apr 2015 21:08:46 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: Message-ID: ---------- Forwarded message ---------- From: diliup gabadamudalige Date: Tue, Apr 28, 2015 at 6:22 PM Subject: circular movement in pygame To: pygame-users at seul.org Looking at the code on this page lines 47 & 48 http://programarcadegames.com/python_examples/show_file.php?file=sprite_circle_movement.py is there a way to do self.rect.x +*= some value* self.rect.y += some value rather than self.rect.x = self.radius * math.sin(self.angle) + self.center_x self.rect.y = self.radius * math.cos(self.angle) + self.center_y ? I tired it in the code attached and strangely it works ok but only OUTSIDE THE class. When I implement the exact code in a class it does something weird. I can't find where I have gone wrong. Please help. Many thanks in advance. Diliup Gabadamudalige ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** -------------- next part -------------- import sys, os, pygame, itertools from math import sin,cos,pi, radians from pygame.locals import * os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50,50) #Set window position pygame.init() clock = pygame.time.Clock() FPS = 1000 SCREENW = 800 #screen width SCREENH = 740 #screen height BLACK = (0, 0, 0) BLUE = (0, 0, 255) ORANGE = (128, 100, 30) FONT1= "Cookie-Regular.ttf" SCREEN = pygame.display.set_mode((SCREENW, SCREENH), 0, 32) #display screen clock = pygame.time.Clock() #------------------------------------------------------------------------------- def maketext(msg,fontsize, colour = ORANGE, font = FONT1): mafont = pygame.font.Font(font, fontsize) matext = mafont.render(msg, True, colour) matext = matext.convert_alpha() return matext #------------------------------------------------------------------------------- def print_info(): """""" textcos = maketext(str(round(obj.rect.x, 2)) + " " + str(round(obj.rect.y, 2)), 30) SCREEN.blit(textcos, (obj.rect.x, obj.rect.y + 30)) #------------------------------------------------------------------------------- class object_factory(pygame.sprite.Sprite): def __init__(self, imagelist, xpos = 0, ypos = 0, speedx = 0, speedy = 0, value = 0): """Constructor""" pygame.sprite.Sprite.__init__(self) self.name = "" self.frame = 0 self.imagelist = imagelist self.image = imagelist[self.frame] self.mask = pygame.mask.from_surface(self.image) # pixelmask self.rect = self.image.get_rect() self.rect.x = xpos self.rect.y = ypos self.speedx = speedx self.speedy = speedy self.timer = 0 self.timerlimit = 10 #---------------------------------------------------------------------- def move(self): # wallsprites, Herosprite, looptime self.rect.x += self.speedx self.rect.y += self.speedy #---------------------------------------------------------------------- def update(self): """""" self.image = self.imagelist[self.frame] if self.timer >= self.timerlimit: self.frame += 1 if self.frame >= len(self.imagelist): self.frame = 0 self.timer = 0 self.timer += 1 plat = pygame.image.load("plt0.png").convert_alpha() star = pygame.image.load("gemp0.png").convert_alpha() box = pygame.image.load("crateB.png").convert_alpha() platforms = pygame.sprite.Group() boxes = pygame.sprite.Group() From alan.gauld at btinternet.com Tue Apr 28 19:50:59 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Tue, 28 Apr 2015 18:50:59 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: Message-ID: On 28/04/15 16:38, diliup gabadamudalige wrote: > ---------- Forwarded message ---------- > From: diliup gabadamudalige > Date: Tue, Apr 28, 2015 at 6:22 PM > Subject: circular movement in pygame > To: pygame-users at seul.org It's good that you tried the python-game list for a pygame question. But if pygame-users can't give a definitive answer then its even less likely that the tutor list will. Although you might need to allow a full 24 hours to get answers, email is not an instant delivery mechanism. > Looking at the code on this page lines 47 & 48 > > http://programarcadegames.com/python_examples/show_file.php?file=sprite_circle_movement.py I didn't look at the code in that tutorial, but... > is there a way to do > self.rect.x +*= some value* > self.rect.y += some value Yes, that's just normal Python syntax. It adds/multiplies the current value of self.rect with "some value"... > rather than > > self.rect.x = self.radius * math.sin(self.angle) + self.center_x > self.rect.y = self.radius * math.cos(self.angle) + self.center_y But its unlikely to have the same effect as this since the above two lines are calculating a new value based on radius, angle, and centre rather than one based on the current values of self.rect > I tired it in the code attached and strangely it works ok but only OUTSIDE > THE class. When I implement the exact code in a class it does something > weird. I can't find where I have gone wrong. I can't see your code but are you sure you are using self in all the appropriate places in your class based code? -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From oscar.j.benjamin at gmail.com Tue Apr 28 20:28:07 2015 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Tue, 28 Apr 2015 19:28:07 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: Message-ID: On 28 April 2015 at 16:38, diliup gabadamudalige wrote: > > Looking at the code on this page lines 47 & 48 > > http://programarcadegames.com/python_examples/show_file.php?file=sprite_circle_movement.py > > is there a way to do > self.rect.x +*= some value* > self.rect.y += some value > > rather than > > self.rect.x = self.radius * math.sin(self.angle) + self.center_x > self.rect.y = self.radius * math.cos(self.angle) + self.center_y There's no way to do that. The second version ignores the previous value of self.rect.x/y. I'm going to guess that the angle has only changed by a small amount delta_angle between iterations in which case there would be a way to do it approximately. The real question is just why though? The second version is correct and will be correct for ever. The first version would only be approximately correct and over time you'd probably find that the position would drift so that the ball was effectively at a different radius. In any case if x = r * sin(theta) then dx/dt = r * cos(theta) * dtheta/dt. Since y = r * cos(theta) that's dy/dt = x * dtheta/dt. So you could update y approximately with: y += x * dtheta/dt * deltat where deltat is your timestep. In your code that would be: self.rect.x += self.rect.y * self.speed self.rect.y -= self.rect.x * self.speed Really what you have now is better though. From oscar.j.benjamin at gmail.com Tue Apr 28 21:00:09 2015 From: oscar.j.benjamin at gmail.com (Oscar Benjamin) Date: Tue, 28 Apr 2015 20:00:09 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: Message-ID: On 28 April 2015 at 19:37, diliup gabadamudalige wrote: > > I thank all those who responded to my question > > Here is the code that I had written. > > When updating is applied to a surface object the rotation works but when it > is applied through a class to an object it goes wrong in about 3 rotations. > As far as I can see the code is the same. What is wrong? If you can correct > some code and show me would help. Your code is too long and complicated for me to read through it all. You should simplify your problem before posting it somewhere like this. Make a simpler program that does something similar but without all the pygame stuff. For example your program might just loop through printing out the positions of the object at different times e.g.: # game.py # # This program simulates a ball moving at constant speed # in a two dimensional space. # # Initial position of ball xpos = 0 ypos = 0 # Horizontal and vertical speed xspeed = 1 yspeed = 2 # Timestep deltat = 0.125 # Run through 10 iterations of simulation for n in range(10): # Update state xpos += xspeed * deltat ypos += yspeed * deltat # Output current state print('Position = (%.3f, %.3f)' % (xpos, ypos)) $ python game.py # Show the output Position = (0.125, 0.250) Position = (0.250, 0.500) Position = (0.375, 0.750) Position = (0.500, 1.000) Position = (0.625, 1.250) Position = (0.750, 1.500) Position = (0.875, 1.750) Position = (1.000, 2.000) Position = (1.125, 2.250) Position = (1.250, 2.500) Once you have made a simpler program carefully explain what it is that you want it to do and show us how what it does is different. Don't expect people on this list to download your code and run it. Also please put your code in the email and not in an attachment and please reply back to the tutor list rather than directly to me. -- Oscar From diliupg at gmail.com Tue Apr 28 20:37:37 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Wed, 29 Apr 2015 00:07:37 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: Message-ID: I thank all those who responded to my question Here is the code that I had written. When updating is applied to a surface object the rotation works but when it is applied through a class to an object it goes wrong in about 3 rotations. As far as I can see the code is the same. What is wrong? If you can correct some code and show me would help. On Tue, Apr 28, 2015 at 11:58 PM, Oscar Benjamin wrote: > On 28 April 2015 at 16:38, diliup gabadamudalige > wrote: > > > > Looking at the code on this page lines 47 & 48 > > > > > http://programarcadegames.com/python_examples/show_file.php?file=sprite_circle_movement.py > > > > is there a way to do > > self.rect.x +*= some value* > > self.rect.y += some value > > > > rather than > > > > self.rect.x = self.radius * math.sin(self.angle) + self.center_x > > self.rect.y = self.radius * math.cos(self.angle) + self.center_y > > There's no way to do that. The second version ignores the previous > value of self.rect.x/y. > > I'm going to guess that the angle has only changed by a small amount > delta_angle between iterations in which case there would be a way to > do it approximately. > > The real question is just why though? The second version is correct > and will be correct for ever. The first version would only be > approximately correct and over time you'd probably find that the > position would drift so that the ball was effectively at a different > radius. > > In any case if > x = r * sin(theta) > then > dx/dt = r * cos(theta) * dtheta/dt. > Since > y = r * cos(theta) that's > dy/dt = x * dtheta/dt. > So you could update y approximately with: > y += x * dtheta/dt * deltat > where deltat is your timestep. In your code that would be: > self.rect.x += self.rect.y * self.speed > self.rect.y -= self.rect.x * self.speed > > Really what you have now is better though. > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** -------------- next part -------------- import sys, os, pygame, itertools from math import sin,cos,pi, radians from pygame.locals import * os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50,50) #Set window position pygame.init() clock = pygame.time.Clock() FPS = 1000 SCREENW = 800 #screen width SCREENH = 740 #screen height BLACK = (0, 0, 0) BLUE = (0, 0, 255) ORANGE = (128, 100, 30) FONT1= "Cookie-Regular.ttf" SCREEN = pygame.display.set_mode((SCREENW, SCREENH), 0, 32) #display screen clock = pygame.time.Clock() #------------------------------------------------------------------------------- def maketext(msg,fontsize, colour = ORANGE, font = FONT1): mafont = pygame.font.Font(font, fontsize) matext = mafont.render(msg, True, colour) matext = matext.convert_alpha() return matext #------------------------------------------------------------------------------- def print_info(): """""" textcos = maketext(str(round(obj.rect.x, 2)) + " " + str(round(obj.rect.y, 2)), 30) SCREEN.blit(textcos, (obj.rect.x, obj.rect.y + 30)) #------------------------------------------------------------------------------- class object_factory(pygame.sprite.Sprite): def __init__(self, imagelist, xpos, ypos, speedx = 0, speedy = 0, value = 0): """Constructor""" pygame.sprite.Sprite.__init__(self) self.name = "" self.frame = 0 self.imagelist = imagelist self.image = imagelist[self.frame] self.mask = pygame.mask.from_surface(self.image) # pixelmask self.rect = self.image.get_rect() self.rect.x = xpos self.rect.y = ypos #self.speedx = speedx #self.speedy = speedy self.timer = 0 self.timerlimit = 10 #---------------------------------------------------------------------- #def move(self): # wallsprites, Herosprite, looptime #self.rect.x += self.speedx #self.rect.y += self.speedy #---------------------------------------------------------------------- def update(self): """""" self.image = self.imagelist[self.frame] if self.timer >= self.timerlimit: self.frame += 1 if self.frame >= len(self.imagelist): self.frame = 0 self.timer = 0 self.timer += 1 plat = pygame.image.load("plt0.png").convert_alpha() star = pygame.image.load("gemp0.png").convert_alpha() #box = pygame.image.load("crateB.png").convert_alpha() platforms = pygame.sprite.Group() boxes = pygame.sprite.Group() rotcenx = SCREENW/2 rotceny = SCREENH/2 radius = 200 angle = radians(90) #pi/4 # starting angle 45 degrees omega = radians(5) #Angular velocity m = rotcenx + radius * cos(angle) #Starting position x n = rotceny - radius * sin(angle) #Starting position y for _ in itertools.repeat(None, 1): madyax = SCREENW/2 madyay = SCREENH/2 araya = 200 konaya = radians(180) #pi/4 # starting angle 45 degrees konika_pravegaya = radians(5) #Angular velocity a = madyax + (araya * cos(konaya)) #Starting position x b = madyay - (araya * sin(konaya)) #Startinh position y plat = object_factory([plat], a, b) plat.araya = araya plat.konaya = konaya plat.kp = konika_pravegaya platforms.add(plat) while True: ms = clock.tick(FPS) # milliseconds passed since last frame #looptime = milliseconds / 1000.0 # seconds passed since last frame SCREEN.fill((BLACK)) pygame.draw.circle(SCREEN, BLUE, (SCREENW / 2, SCREENH / 2), 5) ##----------------------------------------------------------- SCREEN.blit(star, (m, n)) # Draw current x,y angle = angle + omega # New angle, we add angular velocity m = m + radius * omega * cos(angle + pi / 2) # New x n = n - radius * omega * sin(angle + pi / 2) # New y ##----------------------------------------------------------- # show object anchored to center of rotation pygame.draw.line(SCREEN, ORANGE, (rotcenx, rotceny), (m, n)) text = maketext(str(radius), 30) SCREEN.blit(text, (m, n - 40)) text = maketext((str(round(m, 2)) + " " + str(round(n, 2))), 30) SCREEN.blit(text, (m, n + 40)) # Draw current x,y ##------------------------------------------------------------------ for plat in platforms: plat.konaya = plat.konaya + plat.kp plat.rect.x = plat.rect.x + plat.araya * plat.kp * cos(plat.konaya + pi / 2) plat.rect.y = plat.rect.y - plat.araya * plat.kp * sin(plat.konaya + pi / 2) ##------------------------------------------------------------------------ pygame.draw.line(SCREEN, ORANGE, (madyax, madyay), (plat.rect.x, plat.rect.y)) platforms.update() platforms.draw(SCREEN) pygame.event.pump() keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): pygame.quit() sys.exit() pygame.display.update() pygame.time.wait(100) From paradox at pobox.com Tue Apr 28 23:40:55 2015 From: paradox at pobox.com (Thomas C. Hicks) Date: Wed, 29 Apr 2015 05:40:55 +0800 Subject: [Tutor] How to output dictionary data to CSV file :p: In-Reply-To: References: <553F4A2D.8030500@pobox.com> Message-ID: <553FFE67.50008@pobox.com> On 04/28/2015 09:43 PM, Alan Gauld wrote: > You could consider JSON too. > JSON looks a lot like a Python dictionary of strings so is > almost a perfect match to your data. Sounds great, I'll check it out. Thanks! thomas ============================== Thomas C. Hicks, MD, MPH Training Manager, Gansu Gateway Lanzhou, Gansu, PR China From davea at davea.name Wed Apr 29 01:16:26 2015 From: davea at davea.name (Dave Angel) Date: Tue, 28 Apr 2015 19:16:26 -0400 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: Message-ID: <554014CA.90601@davea.name> On 04/28/2015 02:37 PM, diliup gabadamudalige wrote: > I thank all those who responded to my question > > Here is the code that I had written. > > When updating is applied to a surface object the rotation works but when it > is applied through a class to an object it goes wrong in about 3 rotations. > As far as I can see the code is the same. What is wrong? If you can correct > some code and show me would help. > By top-posting, you're messing up the readability of your response. And by trying to use an attachment, you're messing up a large portion of the people reading this thread. Post a simplified example, inline in your message, and *following* any quote you're using. If your symptom is that the data diverges eventually from the intended trajectory, the problem is that you're accumulating errors. Each point you do you're rounding the calculation by storing it in finite precision. After enough roundoffs, the error becomes visible. If you need to reliably move an object in a circle, you'll want to store the location in angular terms, center, radius, and angle. Then each time around the loop, increment the angle by a non-rounded amount, and recalculate the x/y coordinates. -- DaveA From jugurtha.hadjar at gmail.com Wed Apr 29 05:06:05 2015 From: jugurtha.hadjar at gmail.com (Jugurtha Hadjar) Date: Wed, 29 Apr 2015 04:06:05 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python Message-ID: <55404A9D.5010103@gmail.com> Hello, all.. I have a class with methods that access a database (SQLite3). I have included an excerpt showin reading and writing and would like to know if I'm doing it right. (i.e: Is it bad code and what to improve). Here are some improvements and my rationale (check my thinking): - Initially, each method had its SQL statement(s) inside, but I grouped all statements in a dictionary, with operations as keys, as a class 'constant' as per previous advice on this mailing list. - Each method used sqlite3 module on its own, but it was repetitive so I put that part in its own method `init_db` that returns a tuple consisting in a connection and a cursor. - Sometimes there was an exception raised, so I used `try` in `init_db`. - Methods closed the connection themselves, so I used `with` in `init_db` instead of `try`, as it would close the connection automatically and rollback (I hope I'm not making this up). Here's the excerpt (`DB_FILES` and `QUERIES` are not included here for more clarity). Thank you. def __init__(self, phone): # Get preliminary information on user and make them # available. self.phone = phone self.known = self.find() if self.known: self.balance = self.get_balance() else: self.balance = None def init_db(self): with sqlite3.connect(self.DB_FILE) as conn: return conn, conn.cursor() def find(self): '''Find the phone in the users database.''' (__, cursor) = self.init_db() try: cursor.execute( self.QUERIES['FIND_PHONE'], (self.phone,) ) found = cursor.fetchone() return True if found else False except Exception as e: return self.ERROR.format(e.args[0]) def create(self, seed_balance): ''' Create a database entry for the sender.''' conn, cursor = self.init_db() try: cursor.execute( self.QUERIES['CREATE'], (self.phone, seed_balance) ) conn.commit() except Exception as e: return self.ERROR.format(e.args[0]) -- ~Jugurtha Hadjar, From cybervigilante at gmail.com Wed Apr 29 05:58:39 2015 From: cybervigilante at gmail.com (Jim Mooney Py3winXP) Date: Tue, 28 Apr 2015 20:58:39 -0700 Subject: [Tutor] Function works one time then subsequently fails Message-ID: This is really puzzling me. I'm parsing a string to do some simple math operations and practice tossing functions around. My parser works on the first run, then it continually fails on the same input. """ Takes the name of a binary math operation and two numbers from input, repeatedly, and displays the results until done """ def add(a, b): return a + b def subtract(a, b): return b - a def minus(a, b): return a - b def multiply(a, b): return a * b def divide(a, b): return a / b operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract, '-': minus, 'minus': minus, 'multiply': multiply, '*': multiply, 'times': multiply, 'divide': divide, '/': divide, 'divided': divide} numbers = [] def test_number(astring): """ Input: A string that should represent a valid int or float. Output: An int or float on success. None on failure. """ for make_type in (int, float): try: return make_type(astring) except ValueError: pass return None def parse_string(math_string): """Input: A math string with a verbal or mathematical operation and two valid numbers to operate on. Extra numbers and operations are ignored. Output: A tuple containing a function corresponding to the operation and the two numbers. Returns None on failure. """ operation = None tokens = math_string.split() for token in tokens: if token in operations: operation = operations[token] elif test_number(token) != None: numbers.append(test_number(token)) if len(numbers) > 1: break if operation is None or len(numbers) < 2: return None else: return operation, numbers[0], numbers[1] REPL >>> result = parse_string('1 minus 15') >>> func, number1, number2 = result >>> func(number1, number2) -14 >>> result = parse_string('1 minus 15') >>> print(result) None >>> result = parse_string('1 minus 15') >>> print(result) None >>> -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From cs at zip.com.au Wed Apr 29 06:27:25 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 29 Apr 2015 14:27:25 +1000 Subject: [Tutor] Function works one time then subsequently fails In-Reply-To: References: Message-ID: <20150429042725.GA62479@cskk.homeip.net> On 28Apr2015 20:58, Jim Mooney Py3winXP wrote: >This is really puzzling me. I'm parsing a string to do some simple math >operations and practice tossing functions around. My parser works on the >first run, then it continually fails on the same input. [...] >numbers = [] [...] >def parse_string(math_string): > """Input: A math string with a verbal or mathematical operation > and two valid numbers to operate on. Extra numbers and operations > are ignored. Output: A tuple containing a function corresponding > to the operation and the two numbers. Returns None on failure. > """ > operation = None > tokens = math_string.split() > for token in tokens: > if token in operations: > operation = operations[token] > elif test_number(token) != None: > numbers.append(test_number(token)) > if len(numbers) > 1: > break [...] At a first glance numbers is a global. It is reset to [] at program start, but never again. So you're appending to it forever. I have not investigated further as to how that affects your program's flow. Cheers, Cameron Simpson There are two ways of dealing with this problem: one is complicated and messy, and the other is simple and very elegant. We don't have much time left, so I'll just show you the complicated and messy way. - Richard Feynman, 1981 From cybervigilante at gmail.com Wed Apr 29 07:27:21 2015 From: cybervigilante at gmail.com (Jim Mooney Py3winXP) Date: Tue, 28 Apr 2015 22:27:21 -0700 Subject: [Tutor] Function works one time then subsequently fails In-Reply-To: <20150429042725.GA62479@cskk.homeip.net> References: <20150429042725.GA62479@cskk.homeip.net> Message-ID: On 28 April 2015 at 21:27, Cameron Simpson wrote: > At a first glance numbers is a global. It is reset to [] at program start, > but never again. So you're appending to it forever. I have not investigated > further as to how that affects your program's flow. > > Cheers, > Cameron Simpson > Took you less time to find that than me. I, of course, realized I forgot to empty the number list on each time through the parse loop, After I posted ;') Seems to work okay otherwise, although criticism of Pythonicity is welcome. I just wanted to practice tossing functions around. I'll put it into a user input loop and work it. It won't catch everything. I have to study regexes for that. At this point I'm starting to lose track and have to think of better ways to organize so I recall and understand what I'm doing. I know there are general tuts on that but that's just reading. Is there a python-specific tut on it where I could follow actual code along with the interpreter to reinforce things? Or, what is the official word for organize-so-you-don't-forget-or-get-confused so I can search google with it? -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From mitesh.budhabhatti at gmail.com Wed Apr 29 08:06:38 2015 From: mitesh.budhabhatti at gmail.com (Mitesh H. Budhabhatti) Date: Wed, 29 Apr 2015 11:36:38 +0530 Subject: [Tutor] Naming conventions In-Reply-To: <20150428151518.GV5663@ando.pearwood.info> References: <20150428151518.GV5663@ando.pearwood.info> Message-ID: Thank you so much Mark, Steven. This will definitely help. I really appreciate. On Tue, Apr 28, 2015 at 8:45 PM, Steven D'Aprano wrote: > On Tue, Apr 28, 2015 at 01:01:04PM +0530, Mitesh H. Budhabhatti wrote: > > Hello Friends, > > > > Can you please suggest good naming conventions/guidelines to following > > while writing Python code? Thanks. > > Most important rule of all: names should be descriptive and > understandable, not too short or cryptic, not so long that they are > painful to use. Very common names may be abbreviated. Names should be > easy to say aloud. > > # Good names > length, len, map, format > > # Bad names > a, the_thing_we_process, szty > > Avoid "funny" or meaningless names: > > pizza = 23 > homework = 5 > print (pizza > homework) > > > It is acceptable to use standard one-letter variable names in > generic functions, especially for algebraic (maths) functions and > short utility functions, e.g.: > > i, j, k: integer loop variables > m, n: other integers > x, y: floats > z: complex numbers > s: string or set > d: dict > L: list (don't use l because it can look like 1) > o: object > u, v: vectors, arrays, sets > > are common choices. But don't over-use one-letter names. > > Otherwise, names should be self-descriptive: > > # Bad > L = get_customers() # list of customers > > # Good > customers = get_customers() > > Use plurals for lists, sets or dicts of some data type, and the singular > for individual data types. E.g.: > > names = ['John', 'Mary', 'Fred', 'Sue'] > for name in names: > process(name) > > > Functions and methods should be verbs or verb-phrases in all lowercase, > for example: > > expand() sort() lift() prepare_database() create_factory() > > Variables holding data values should be nouns: > > page count header footer server client factory > > (Watch out for words which can be both a noun and a verb, like count.) > > Classes should be nouns with initial capitals: > > Car Engine Animal HTTPServer > > and instances should be lowercase: > > server = HTTPServer() > > The exception is if the class is a "small" primitive or simple type, > like built-ins int, str, dict, list etc. But even then, you may choose > to use Initial Capitals instead. > > Modules should follow the all-lowercase name. If possible, modules > should describe what they are about: > > math string io unicodedata > > but it is also acceptable for modules to have an arbitrary name which > you just have to learn: > > pillow flask zope fabric nose > > > > Does this help? > > > -- > Steve > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > From cs at zip.com.au Wed Apr 29 07:40:03 2015 From: cs at zip.com.au (Cameron Simpson) Date: Wed, 29 Apr 2015 15:40:03 +1000 Subject: [Tutor] Function works one time then subsequently fails In-Reply-To: References: Message-ID: <20150429054003.GA43610@cskk.homeip.net> On 28Apr2015 22:27, Jim Mooney Py3winXP wrote: >On 28 April 2015 at 21:27, Cameron Simpson wrote: >> At a first glance numbers is a global. It is reset to [] at program start, >> but never again. So you're appending to it forever. I have not investigated >> further as to how that affects your program's flow. > >Took you less time to find that than me. I, of course, realized I forgot to >empty the number list on each time through the parse loop, After I posted >;') Seems to work okay otherwise, although criticism of Pythonicity is >welcome. I just wanted to practice tossing functions around. I'll put it >into a user input loop and work it. It won't catch everything. I have to >study regexes for that. Basicly, you should almost never have a global variable. There is a host of special circumstances where globals solve some specific problems. But by and large, don't do it without a very concrete reason. If numbers had been local to the parse function you would never have been bitten by this. There's no need for it to be global; you can return the operator and the operands (numbers) easily from the parse function. >At this point I'm starting to lose track and have to think of better ways >to organize so I recall and understand what I'm doing. I know there are >general tuts on that but that's just reading. Is there a python-specific >tut on it where I could follow actual code along with the interpreter to >reinforce things? Or, what is the official word for >organize-so-you-don't-forget-or-get-confused so I can search google with it? "functional decomposition"? One rule of thumb is that functions should be short. That way you can generally keep their purpose and internal oparations in your head in one go, and the whole thing also fits on your screen. As with all things, sometimes that cannot be reasonably achieved, but it is usually so. We can pick over your code as well if you like. Should we? Cheers, Cameron Simpson If this experiment we're doing works, then I will follow up and push it as hard as possible. And if it doesn't work, I will write a science-fiction novel where it does work. It's a win-win situation. - John Cramer on his experiment for possible cuasality violation From diliupg at gmail.com Wed Apr 29 09:15:01 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Wed, 29 Apr 2015 12:45:01 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: <554014CA.90601@davea.name> References: <554014CA.90601@davea.name> Message-ID: Thanks all for the responses. Charles Coss? - yes I can write a simple pygame program that makes a sprite move in a circle but it may not be the style and order that many may approve or accept. I consider myself a student. :) No one has pointed out why the object moves in a circle properly in the bit of code where it is addressed directly and why it does not when the same code is applied thru a class. I know that an object can be made to move around the circumference of a circle by constantly calculating the point and giving the x and y values 1. x = some code That is what I used and it worked. I was trying to find how we can do the same thing by updating the current position by doing 2. x += some code Above 1 works. 2 does not. Why is that? Both the same code. The same variable is used with different names cause some others were confused when they were the same. I hope this time I have answered correctly. No more attachments. (e mail or otherwise. :) ) From jsolis1 at stedwards.edu Wed Apr 29 03:24:57 2015 From: jsolis1 at stedwards.edu (Jacqueline G Solis) Date: Tue, 28 Apr 2015 20:24:57 -0500 (CDT) Subject: [Tutor] if then statements In-Reply-To: <187312571.270100.1430270451101.JavaMail.zimbra@stedwards.edu> Message-ID: <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> hello, I keep getting a syntax error. Could you please explain why that happens and how to correct it. def main (): print( "Welcome to Gonzo Burger!") order= int(input("Enter 1 if you want a hamburger,\ or 2 if you want a cheeseburger:" )) if order == 1 : print("order: 1") else: print("Order: 2") drink=int(input("Thank you! Next, enter a 1 if you want a Coke,\ or a 2 if you want a Sprite:") if drink == 1 : print("Order: 1") else: print("Order: 2") print("Thank you! You ordered:") if order == 1: print("- Hamburger") else: print("- Cheeseburger") if drink == 1 : print("- Coke") else: print("- Sprite") main () -Jackie p.s: the error happens in the second if statement. From alan.gauld at btinternet.com Wed Apr 29 09:48:21 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 08:48:21 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> Message-ID: On 29/04/15 08:15, diliup gabadamudalige wrote: > 1. x = some code > > That is what I used and it worked. I was trying to find how we can do the > same thing by updating the current position by doing > > 2. x += some code > Above 1 works. 2 does not. Why is that? Because they do completely different things! 1 is simply x = some code 2 is x = x + some code In 2 you are adding x to some code. Of course they don't work the same. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From breamoreboy at yahoo.co.uk Wed Apr 29 10:01:41 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 29 Apr 2015 09:01:41 +0100 Subject: [Tutor] if then statements In-Reply-To: <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> References: <187312571.270100.1430270451101.JavaMail.zimbra@stedwards.edu> <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> Message-ID: On 29/04/2015 02:24, Jacqueline G Solis wrote: > hello, > > I keep getting a syntax error. Could you please explain why that happens and how to correct it. > > > def main (): > print( "Welcome to Gonzo Burger!") > order= int(input("Enter 1 if you want a hamburger,\ > or 2 if you want a cheeseburger:" )) > if order == 1 : > print("order: 1") > else: > print("Order: 2") > > drink=int(input("Thank you! Next, enter a 1 if you want a Coke,\ > or a 2 if you want a Sprite:") > if drink == 1 : > print("Order: 1") > else: > print("Order: 2") > > print("Thank you! You ordered:") > if order == 1: > print("- Hamburger") > else: > print("- Cheeseburger") > if drink == 1 : > print("- Coke") > else: > print("- Sprite") > > main () > > > > > -Jackie > p.s: the error happens in the second if statement. > No it doesn't :) That's where it gets found, but the error is actually before then, and as a learning exercise I'll let you find it. Look very carefully at "order=..." and "drink=..." and I'm sure you'll spot the difference. -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From alan.gauld at btinternet.com Wed Apr 29 10:06:12 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 09:06:12 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: <55404A9D.5010103@gmail.com> References: <55404A9D.5010103@gmail.com> Message-ID: On 29/04/15 04:06, Jugurtha Hadjar wrote: > - Initially, each method had its SQL statement(s) inside, but I grouped > all statements in a dictionary, with operations as keys, as a class > 'constant' as per previous advice on this mailing list. We can't see that in the code you posted. In principle its an acceptable strategy. A close alternative would be to name the queries as explicit class variables. So for example you would use: cur.execute(self.find_phone_query,(....)) Its less typing and less error prone in that you get a syntax error on mistyping rather than a run time exception. > - Each method used sqlite3 module on its own, but it was repetitive so I > put that part in its own method `init_db` that returns a tuple > consisting in a connection and a cursor. That's a common approach. > - Sometimes there was an exception raised, so I used `try` in `init_db`. > > - Methods closed the connection themselves, so I used `with` in > `init_db` instead of `try`, as it would close the connection > automatically and rollback (I hope I'm not making this up). Try/except and with do different things but in this case you can get away with it. The only loss is that your errors here are not formatted in the same way as the other messages. > Here's the excerpt > def __init__(self, phone): > > # Get preliminary information on user and make them > # available. Consider using docstrings rather than comments to describe the method I see you do that below... > self.phone = phone > self.known = self.find() > > if self.known: > self.balance = self.get_balance() > else: > self.balance = None > > def init_db(self): > with sqlite3.connect(self.DB_FILE) as conn: > return conn, conn.cursor() > > def find(self): > '''Find the phone in the users database.''' > > (__, cursor) = self.init_db() Don't use the __ 'variable' here, be explicit, it makes maintenance much easier. > try: > cursor.execute( > self.QUERIES['FIND_PHONE'], > (self.phone,) > ) > found = cursor.fetchone() > return True if found else False > except Exception as e: > return self.ERROR.format(e.args[0]) Don't catch Exception, it's too wide. Catch the actual errors that might arise, be as specific as possible. > def create(self, seed_balance): > ''' Create a database entry for the sender.''' > > conn, cursor = self.init_db() > try: > cursor.execute( > self.QUERIES['CREATE'], > (self.phone, seed_balance) > ) > conn.commit() > except Exception as e: > return self.ERROR.format(e.args[0]) as above -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Wed Apr 29 10:08:35 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 09:08:35 +0100 Subject: [Tutor] if then statements In-Reply-To: <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> References: <187312571.270100.1430270451101.JavaMail.zimbra@stedwards.edu> <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> Message-ID: On 29/04/15 02:24, Jacqueline G Solis wrote: > hello, > > I keep getting a syntax error. If you get an error always include the full message text in your queries. It helps enormously in finding the problem. > Could you please explain why that happens and how to correct it. But in this case its obvious... > def main (): > print( "Welcome to Gonzo Burger!") > order= int(input("Enter 1 if you want a hamburger,\ > or 2 if you want a cheeseburger:" )) > if order == 1 : > print("order: 1") > else: > print("Order: 2") > > drink=int(input("Thank you! Next, enter a 1 if you want a Coke,\ > or a 2 if you want a Sprite:") Count the parentheses in the line above. > p.s: the error happens in the second if statement. If you'd sent the error message you wouldn't have to tell us that :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Wed Apr 29 10:21:06 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 09:21:06 +0100 Subject: [Tutor] Function works one time then subsequently fails In-Reply-To: References: Message-ID: On 29/04/15 04:58, Jim Mooney Py3winXP wrote: > numbers = [] Note that you chose to make this global. > def parse_string(math_string): > """Input: A math string with a verbal or mathematical operation > and two valid numbers to operate on. Extra numbers and operations > are ignored. Output: A tuple containing a function corresponding > to the operation and the two numbers. Returns None on failure. > """ General comment. returning a mixture of None and valid data is a recipe for confusion later. Its better to fail by raising an exception, say a ValueError for example, or even create a bespoke error. > operation = None > tokens = math_string.split() > for token in tokens: > if token in operations: > operation = operations[token] > elif test_number(token) != None: > numbers.append(test_number(token)) > if len(numbers) > 1: > break > if operation is None or len(numbers) < 2: > return None > else: > return operation, numbers[0], numbers[1] > > REPL >>>> result = parse_string('1 minus 15') >>>> func, number1, number2 = result >>>> func(number1, number2) > -14 >>>> result = parse_string('1 minus 15') >>>> print(result) > None You never empty numbers so it already contains >1 numbers. Your loop breaks. And operation is None. So you return None. That's why raising an error with suitable text would be clearer. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Wed Apr 29 10:26:39 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 09:26:39 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> Message-ID: <554095BF.2000208@btinternet.com> On 29/04/15 09:03, diliup gabadamudalige wrote: > Thank you Alan. Understood. I already knew that. My question is > > How to to do it the second way. > some code = what? > The point is you cannot do it. The second approach always uses the current value of x. The first approach may or may not use the current value of x. If it does not use x then the += style cannot be made to work (unless you tag a -x on at the end! x = 42 x += 42-x Which is just stupid. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Wed Apr 29 10:50:32 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 29 Apr 2015 10:50:32 +0200 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python References: <55404A9D.5010103@gmail.com> Message-ID: Jugurtha Hadjar wrote: > I have a class with methods that access a database (SQLite3). I have > included an excerpt showin reading and writing and would like to know if > I'm doing it right. (i.e: Is it bad code and what to improve). > > Here are some improvements and my rationale (check my thinking): > > - Initially, each method had its SQL statement(s) inside, but I grouped > all statements in a dictionary, with operations as keys, as a class > 'constant' as per previous advice on this mailing list. > > - Each method used sqlite3 module on its own, but it was repetitive so I > put that part in its own method `init_db` that returns a tuple > consisting in a connection and a cursor. > > - Sometimes there was an exception raised, so I used `try` in `init_db`. > > - Methods closed the connection themselves, so I used `with` in > `init_db` instead of `try`, as it would close the connection > automatically and rollback (I hope I'm not making this up). > > Here's the excerpt (`DB_FILES` and `QUERIES` are not included here for > more clarity). > > Thank you. > > > > def __init__(self, phone): > > # Get preliminary information on user and make them > # available. > > self.phone = phone > self.known = self.find() > > if self.known: > self.balance = self.get_balance() > else: >> self.balance = None > > def init_db(self): > with sqlite3.connect(self.DB_FILE) as conn: > return conn, conn.cursor() > > def find(self): > '''Find the phone in the users database.''' > > (__, cursor) = self.init_db() > try: > cursor.execute( > self.QUERIES['FIND_PHONE'], > (self.phone,) > ) > found = cursor.fetchone() > return True if found else False > except Exception as e: > return self.ERROR.format(e.args[0]) > > def create(self, seed_balance): > ''' Create a database entry for the sender.''' > > conn, cursor = self.init_db() > try: > cursor.execute( > self.QUERIES['CREATE'], > (self.phone, seed_balan>ce) > ) > conn.commit() > except Exception as e: > return self.ERROR.format(e.args[0]) My random observations: (1) find() and create() look very similar. Try hard to factor out common code. You might even combine it into a single method ensure_balance(phone). (2) According to https://docs.python.org/dev/library/sqlite3.html#using-the-connection-as-a-context-manager - the context manager automatically commits - you can run sql directly on the connection It might by a good idea to refactor init_db() to just return the connection and then use it as with self.init_db() as conn: return conn.execute( self.QUERIES['FIND_PHONE'], (self.phone,)).fetchone() is not None If you need a cursor you can easily get one from the connection. If you want more complex handling later you can always turn init_db() into a contextmanager (see ). (3) Catching Exception is overly broad. You will also catch a typo like cursor.execute( self.QUERIES['CERATE'], (self.phone, seed_balance) ) where the proper fix is to modify the script. Only catch exceptions that you can actually handle. Example: a table doesn't exist, and you want to create it lazily on first access. Let all other exceptions just bubble up. It may seem lazy, but a complete traceback is invaluable for identifying and fixing a bug. (4) self.ERROR.format(e.args[0]) is probably a string with len() > 0, and thus True in a boolean context. >From that follows an exception in the find() method in > self.known = self.find() causes the following if-suite to be run > if self.known: > self.balance = self.get_balance() and if get_balance() has a same idea of proper exception handling self.balance will end up containing an error message. (5) From point (4) I conclude that you don't have unit tests that cover your code. You should really write some of these before pondering about stylistic issues. Unit tests - help avoid errors - make changes in the code less of a gamble because if the tests succeed after the change you can be confident the change didn't introduce an error - what you might not expect: how drastically tests affect the style of your code. You'll see yourself thinking "How can I test that?" with every line of code that you write, and that alone will improve the quality of your code. A simple example is your self.find(). How would you test that with different phone numbers? That's easier when you can pass the phone number as an argument, so you might change the method's signature. From duxbuz at hotmail.com Wed Apr 29 11:44:28 2015 From: duxbuz at hotmail.com (Ian D) Date: Wed, 29 Apr 2015 09:44:28 +0000 Subject: [Tutor] comparison on Types Message-ID: I was looking at the example code below. I am using python 2.7. I am wondering why when I substitute the while n! = "guess" to while n!= guess (<-- no quotes) I get a problem? The Type string is used for the first conditional comparison in the outer While loop, but afterwards the Type is an int. I would have expected the guess variable to be used as Type int as it seems to be cast in the raw_input statement and would be comparable to another int that's stored in variable n. Thanks import random n = random.randint(1, 99) guess = int(raw_input("Enter an integer from 1 to 99: ")) while n != "guess": print if guess < n: print "guess is low" guess = int(raw_input("Enter an integer from 1 to 99: ")) elif guess> n: print "guess is high" guess = int(raw_input("Enter an integer from 1 to 99: ")) else: print "you guessed it!" break print From __peter__ at web.de Wed Apr 29 12:51:54 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 29 Apr 2015 12:51:54 +0200 Subject: [Tutor] comparison on Types References: Message-ID: Ian D wrote: > I was looking at the example code below. I am using python 2.7. > > I am wondering why when I substitute the while n! = "guess" to while n!= > guess (<-- no quotes) I get a problem? What is that problem? The only thing I see is that the > else: > print "you guessed it!" > break branch is never executed. You remove it and instead put the > print "you guessed it!" statement after the loop. > The Type string is used for the first conditional comparison in the outer > While loop, but afterwards the Type is an int. Not even that. The guess name is bound to an integer before the loop is entered: > guess = int(raw_input("Enter an integer from 1 to 99: ")) while n != guess: ... > I would have expected the guess variable to be used as Type int as it > seems to be cast in the raw_input statement and would be comparable to > another int that's stored in variable n. Thanks You have that right. > import random > n = random.randint(1, 99) > guess = int(raw_input("Enter an integer from 1 to 99: ")) > while n != "guess": > print > if guess < n: > print "guess is low" > guess = int(raw_input("Enter an integer from 1 to 99: ")) > elif guess> n: > print "guess is high" > guess = int(raw_input("Enter an integer from 1 to 99: ")) > else: > print "you guessed it!" > break > print From steve at pearwood.info Wed Apr 29 13:14:06 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 29 Apr 2015 21:14:06 +1000 Subject: [Tutor] comparison on Types In-Reply-To: References: Message-ID: <20150429111404.GZ5663@ando.pearwood.info> On Wed, Apr 29, 2015 at 09:44:28AM +0000, Ian D wrote: > I was looking at the example code below. I am using python 2.7. > > I am wondering why when I substitute the while n! = "guess" to while > n!= guess (<-- no quotes) I get a problem? Really? What sort of problem? It looks okay to me, although I haven't run it. > The Type string is used for the first conditional comparison in the > outer While loop, but afterwards the Type is an int. > > I would have expected the guess variable to be used as Type int as it > seems to be cast in the raw_input statement and would be comparable to > another int that's stored in variable n. Thanks I'm having difficulty understanding your question. It might help if you explain what you think the code should do, versus what it actually does. Do you get an error? Then post the full error traceback, starting from the line "Traceback" to the end. It also might help to understand that in Python, *variables* don't have types, but values do. Variables can take any value, and take on the type of that value until such time as they change to a different value: py> x = "Hello" py> type(x) py> x = 23 py> type(x) Looking at your code, I can see only one obvious (to me) problem: > import random > n = random.randint(1, 99) > guess = int(raw_input("Enter an integer from 1 to 99: ")) > while n != "guess": By using the string "guess", you guarantee that n is *never* equal on the first test. That means that the loop will be entered. If you remove the quotation marks, and compare n != guess (here guess is the variable, not the literal string) then if your guess happens to be correct on the first time, the while loop will not be entered and the program will just end. print > if guess < n: > print "guess is low" > guess = int(raw_input("Enter an integer from 1 to 99: ")) > elif guess> n: > print "guess is high" > guess = int(raw_input("Enter an integer from 1 to 99: ")) > else: > print "you guessed it!" > break > print Try this instead: import random n = random.randint(1, 99) guess = 0 # Guaranteed to not equal n. while n != guess: guess = int(raw_input("Enter an integer from 1 to 99: ")) print if guess < n: print "guess is too low" elif guess > n: print "guess is too high" else: print "guessed correctly!" Does that help? -- Steve From steve at pearwood.info Wed Apr 29 13:27:21 2015 From: steve at pearwood.info (Steven D'Aprano) Date: Wed, 29 Apr 2015 21:27:21 +1000 Subject: [Tutor] if then statements In-Reply-To: <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> References: <187312571.270100.1430270451101.JavaMail.zimbra@stedwards.edu> <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> Message-ID: <20150429112721.GA5663@ando.pearwood.info> On Tue, Apr 28, 2015 at 08:24:57PM -0500, Jacqueline G Solis wrote: > hello, > > I keep getting a syntax error. Could you please explain why that > happens and how to correct it. Syntax errors are sometimes a bit tricky. Usually, they tell you were the error is: py> if (x + 1: File "", line 1 if (x + 1: ^ SyntaxError: invalid syntax Notice the blank line immediately before "SyntaxError"? If you look carefully, you will see a caret ^ which points to the ":" colon in the line before. (In your email, it may not quite line up correctly, but in the Python interpreter and the console, they should like up.) That should make it obvious that I am missing a closing parenthesis before the colon. But sometimes Python doesn't notice the syntax error until the line *after* the actual problem: py> x = (y + 1 ... if x: File "", line 2 if x: ^ SyntaxError: invalid syntax The actual problem is that I am missing a round bracket in the previous line, but Python doesn't realise it until it gets to the colon. Does that help? -- Steve From davea at davea.name Wed Apr 29 14:05:47 2015 From: davea at davea.name (Dave Angel) Date: Wed, 29 Apr 2015 08:05:47 -0400 Subject: [Tutor] if then statements In-Reply-To: <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> References: <930077296.270499.1430270697882.JavaMail.zimbra@stedwards.edu> Message-ID: <5540C91B.1080505@davea.name> On 04/28/2015 09:24 PM, Jacqueline G Solis wrote: > hello, > > I keep getting a syntax error. Could you please explain why that happens and how to correct it. > > > def main (): > print( "Welcome to Gonzo Burger!") > order= int(input("Enter 1 if you want a hamburger,\ > or 2 if you want a cheeseburger:" )) > if order == 1 : > print("order: 1") > else: > print("Order: 2") > > drink=int(input("Thank you! Next, enter a 1 if you want a Coke,\ > or a 2 if you want a Sprite:") > if drink == 1 : The line before this one has a missing right paren at the end. you close the input() function, but not the int() function. So the next thing would have to be a comma, not a reserved token "if" > print("Order: 1") > else: > print("Order: 2") > > print("Thank you! You ordered:") > if order == 1: > print("- Hamburger") > else: > print("- Cheeseburger") > if drink == 1 : > print("- Coke") > else: > print("- Sprite") > > main () > > > > > -Jackie > p.s: the error happens in the second if statement. That's a good hint. Better would be to include the full traceback with the error message, instead of a one-word summary. No matter in this caswe, but it's a good habit to get into. Incidentally, for syntax errors, it's pretty common for the real problem to be in the line before, or even earlier. I'd assume this error pointed at the 'if'. So you're really only going back one token. -- DaveA From duxbuz at hotmail.com Wed Apr 29 14:23:20 2015 From: duxbuz at hotmail.com (Ian D) Date: Wed, 29 Apr 2015 12:23:20 +0000 Subject: [Tutor] comparison on Types In-Reply-To: <20150429111404.GZ5663@ando.pearwood.info> References: , <20150429111404.GZ5663@ando.pearwood.info> Message-ID: Ok thanks. I thought it would be better with just a while True loop; for simple clarity. ---------------------------------------- > Date: Wed, 29 Apr 2015 21:14:06 +1000 > From: steve at pearwood.info > To: tutor at python.org > Subject: Re: [Tutor] comparison on Types > > On Wed, Apr 29, 2015 at 09:44:28AM +0000, Ian D wrote: > >> I was looking at the example code below. I am using python 2.7. >> >> I am wondering why when I substitute the while n! = "guess" to while >> n!= guess (<-- no quotes) I get a problem? > > Really? What sort of problem? It looks okay to me, although I haven't > run it. > > >> The Type string is used for the first conditional comparison in the >> outer While loop, but afterwards the Type is an int. >> >> I would have expected the guess variable to be used as Type int as it >> seems to be cast in the raw_input statement and would be comparable to >> another int that's stored in variable n. Thanks > > I'm having difficulty understanding your question. It might help if you > explain what you think the code should do, versus what it actually does. > Do you get an error? Then post the full error traceback, starting from > the line "Traceback" to the end. > > It also might help to understand that in Python, *variables* don't have > types, but values do. Variables can take any value, and take on the type > of that value until such time as they change to a different value: > > py> x = "Hello" > py> type(x) > > py> x = 23 > py> type(x) > > > > > > Looking at your code, I can see only one obvious (to me) problem: > >> import random >> n = random.randint(1, 99) >> guess = int(raw_input("Enter an integer from 1 to 99: ")) >> while n != "guess": > > By using the string "guess", you guarantee that n is *never* equal on > the first test. That means that the loop will be entered. If you remove > the quotation marks, and compare n != guess (here guess is the variable, > not the literal string) then if your guess happens to be correct on the > first time, the while loop will not be entered and the program will just > end. > > print >> if guess < n: >> print "guess is low" >> guess = int(raw_input("Enter an integer from 1 to 99: ")) >> elif guess> n: >> print "guess is high" >> guess = int(raw_input("Enter an integer from 1 to 99: ")) >> else: >> print "you guessed it!" >> break >> print > > > Try this instead: > > > import random > n = random.randint(1, 99) > guess = 0 # Guaranteed to not equal n. > while n != guess: > guess = int(raw_input("Enter an integer from 1 to 99: ")) > print > if guess < n: > print "guess is too low" > elif guess> n: > print "guess is too high" > else: > print "guessed correctly!" > > > > > Does that help? > > > > -- > Steve > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From davea at davea.name Wed Apr 29 14:32:29 2015 From: davea at davea.name (Dave Angel) Date: Wed, 29 Apr 2015 08:32:29 -0400 Subject: [Tutor] circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> Message-ID: <5540CF5D.4050105@davea.name> On 04/29/2015 03:15 AM, diliup gabadamudalige wrote: > Thanks all for the responses. > Charles Coss? - yes I can write a simple pygame program that makes a > sprite move in a circle but it may not be the style and order that many may > approve or accept. I consider myself a student. :) > No one has pointed out why the object moves in a circle properly in the bit > of code where it is addressed directly and why it does not when the same > code is applied thru a class. > I know that an object can be made to move around the circumference of a > circle by constantly calculating the point and giving the x and y values > > 1. x = some code > > That is what I used and it worked. I was trying to find how we can do the > same thing by updating the current position by doing > > 2. x += some code 2. x += some different code > Above 1 works. 2 does not. Why is that? Because there is always some little error in the value you're adding to x, since it's a floating point value calculated using transcendentals. If you're going to loop thousands of times, those little errors add up. Sometime try measuring a mile using two 12-inch rulers, placing each one before picking up the previous. By the time you're done, you'll probably be off a hundred feet. > > Both the same code. Not at all the same. > The same variable is used with different names cause > some others were confused when they were the same. > > I hope this time I have answered correctly. No more attachments. (e mail > or otherwise. :) ) > I can't necessarily understand the code since you use pygame and I'm not familiar with pygame. In your itertools loop, you always reset the angle back to 100 degrees. In your while loop, you issue a call to draw.circle(). Perhaps that's the working code you're talking about. -- DaveA From fomcl at yahoo.com Wed Apr 29 14:47:18 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 29 Apr 2015 05:47:18 -0700 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths Message-ID: <1430311638.32035.YahooMailBasic@web163802.mail.gq1.yahoo.com> Hello, Windows has the 'feature' that the CD command does not work with UNC paths. So in the code below, I cannot use the 'cwd' parameter of subprocess.Popen. Therefore I use pushd/popd to accomplish the same effect. Is there a better way to do this? (other than using full path names everywhere, or os.chdir). Would it be a useful improvement of Python itself if cwd also works with UNC path? import sys import os import getpass import subprocess path = r'\\server\share\possibly with\space' executable = 'blah.exe' username = os.getenv("USERNAME") password = getpass.getpass("Enter password: ") infile = sys.argv[1] outfile = sys.argv[2] cmds = ['pushd "%s" &&' % path, executable, username, password, infile, outfile, "&& popd"] result = subprocess.Popen(" ".join(cmds), shell=True) error = result.stderr if error: raise RuntimeError(error.read()) Regards, Albert-Jan PS: Python 2.7 on Windows 7 32 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ All right, but apart from the sanitation, the medicine, education, wine, public order, irrigation, roads, a fresh water system, and public health, what have the Romans ever done for us? ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ From davea at davea.name Wed Apr 29 16:02:12 2015 From: davea at davea.name (Dave Angel) Date: Wed, 29 Apr 2015 10:02:12 -0400 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: <1430311638.32035.YahooMailBasic@web163802.mail.gq1.yahoo.com> References: <1430311638.32035.YahooMailBasic@web163802.mail.gq1.yahoo.com> Message-ID: <5540E464.5090003@davea.name> On 04/29/2015 08:47 AM, Albert-Jan Roskam wrote: > Hello, > > Windows has the 'feature' that the CD command does not work with UNC paths. > So in the code below, I cannot use the 'cwd' parameter of subprocess.Popen. > Therefore I use pushd/popd to accomplish the same effect. Is there a better way to do this? > (other than using full path names everywhere, or os.chdir). Would it be a useful improvement > of Python itself if cwd also works with UNC path? > > import sys > import os > import getpass > import subprocess > > path = r'\\server\share\possibly with\space' > executable = 'blah.exe' > username = os.getenv("USERNAME") > password = getpass.getpass("Enter password: ") > infile = sys.argv[1] > outfile = sys.argv[2] > cmds = ['pushd "%s" &&' % path, executable, username, password, infile, outfile, "&& popd"] > > result = subprocess.Popen(" ".join(cmds), shell=True) > error = result.stderr > if error: > raise RuntimeError(error.read()) > > Regards, > > Albert-Jan > > PS: Python 2.7 on Windows 7 32 > Just a comment about Windows. There is a current directory for each lettered drive partition. But a unc name is not necessarily on any known drive. And if executable, infile and outfile might have spaces within them, you need to quote them as well. -- DaveA From __peter__ at web.de Wed Apr 29 16:11:38 2015 From: __peter__ at web.de (Peter Otten) Date: Wed, 29 Apr 2015 16:11:38 +0200 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths References: <1430311638.32035.YahooMailBasic@web163802.mail.gq1.yahoo.com> Message-ID: Albert-Jan Roskam wrote: > Hello, > > Windows has the 'feature' that the CD command does not work with UNC > paths. So in the code below, I cannot use the 'cwd' parameter of > subprocess.Popen. Therefore I use pushd/popd to accomplish the same > effect. Is there a better way to do this? (other than using full path > names everywhere, or os.chdir). Would it be a useful improvement of Python > itself if cwd also works with UNC path? What is the error you get? I don't have Windows to verify, but a quick look into the subprocess source suggests that it uses CreateProcess(). Googling for that finds which states """ lpCurrentDirectory [in, optional] The full path to the current directory for the process. The string can also specify a UNC path. """ > import sys > import os > import getpass > import subprocess > > path = r'\\server\share\possibly with\space' > executable = 'blah.exe' > username = os.getenv("USERNAME") > password = getpass.getpass("Enter password: ") > infile = sys.argv[1] > outfile = sys.argv[2] > cmds = ['pushd "%s" &&' % path, executable, username, password, infile, > outfile, "&& popd"] > > result = subprocess.Popen(" ".join(cmds), shell=True) > error = result.stderr > if error: > raise RuntimeError(error.read()) > > Regards, > > Albert-Jan > > PS: Python 2.7 on Windows 7 32 > > > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > > All right, but apart from the sanitation, the medicine, education, wine, > public order, irrigation, roads, a > > fresh water system, and public health, what have the Romans ever done for > us? > > ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From robertvstepp at gmail.com Wed Apr 29 16:21:39 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 09:21:39 -0500 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? Message-ID: I now have Git installed on my Windows 7 PC at work. The files that I wish to put under Git version control exist on a Solaris 10 workstation. In the Git bash provided, I can ssh into the Solaris 10 machine. I also can the CuteFTP program on my Windows PC to move/copy/etc. files between the two machines. How can I put these Solaris files under version control under these circumstances? I thought I had conceptually seen how to accomplish this via ssh, but if it is doable, my limited knowledge of Git and ssh is insufficient to find the path of success. In order to at least start putting these files under version control, I have created a repository for these files on an intranet drive, used CuteFTP to copy them into the repository from Solaris, and cloned this repository to my Windows PC. My current workflow is very clunky indeed: 1) Bring up file(s) to edit in my Windows editor from my local project working directory. 2) Perform edits. 3) Save edits. 4) In Git bash stage these. 5) Either CuteFTP or scp from Git bash the changed files to Solaris. 6) Test files in Solaris. 7) Repeat. As needed do Git commits and pushes. This is better than what I had been doing. At least I *am* moving into the version control world. But how can I make this (hopefully, lots) better? BTW, I have Git working well at home. As an update I am working on learning how to use Python's unittest module at home. Once I am successful there, I will implement this at work: after the fact on existing projects and from the get-go on new ones. -- boB From cybervigilante at gmail.com Wed Apr 29 17:34:17 2015 From: cybervigilante at gmail.com (Jim Mooney Py3.4.3winXP) Date: Wed, 29 Apr 2015 08:34:17 -0700 Subject: [Tutor] Fwd: Function works one time then subsequently fails In-Reply-To: References: <20150429054003.GA43610@cskk.homeip.net> Message-ID: On 28 April 2015 at 22:40, Cameron Simpson wrote: > > As with all things, sometimes that cannot be reasonably achieved, but it > is usually so. > > We can pick over your code as well if you like. Should we? > > Cheers, > Cameron Simpson Sure, but let me include the full working program after fixup. Although I still have to write another program to feed it random problems to work it out. It's a bit spacey, but I ran it through the pep8 program and it suggested that. I think two spaces between such tiny functions is overkill, though. """ Takes the name of a binary math operation and two numbers from input, repeatedly, and displays the results until done """ def add(a, b): return a + b def subtract(a, b): return b - a def minus(a, b): return a - b def multiply(a, b): return a * b def divide(a, b): return a / b operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract, 'subtracted': subtract, '-': minus, 'minus': minus, 'multiply': multiply, '*': multiply, 'multiplied': multiply, 'times': multiply, 'divide': divide, '/': divide, 'divided': divide} def test_number(astring): """ Input: A string that should represent a valid int or float. Output: An int or float on success. None on failure. """ for make_type in (int, float): try: return make_type(astring) except ValueError: pass return None def parse_string(math_string): """Input: A math string with a verbal or mathematical operation and two valid numbers to operate on. Extra numbers and operations are ignored. Output: A tuple containing a function corresponding to the operation and the two numbers. Returns None on failure. """ operation = None tokens = math_string.split() numbers = [] for token in tokens: if token in operations: operation = operations[token] elif test_number(token) != None: numbers.append(test_number(token)) if len(numbers) > 1: break if operation is None or len(numbers) < 2: return None else: return operation, numbers[0], numbers[1] instructions = '''Enter two numbers and one of the four basid math operations, either mathematical or verbal. i.e. 3 + 2, 12 divided by 14, 10 minus 4, etc. Enter done to quit. ''' try: user_input = input(instructions) while True: if user_input == 'done': break result = parse_string(user_input) if result == None: print("Not a valid math operation.") else: func, num1, num2 = result print(func(num1, num2)) user_input = input() except KeyboardInterrupt: print("Program terminated by user") -- Jim If you only had one hour left to live, would you spend it on Facebook, Twitter, or Google Plus? From jugurtha.hadjar at gmail.com Wed Apr 29 18:03:41 2015 From: jugurtha.hadjar at gmail.com (Jugurtha Hadjar) Date: Wed, 29 Apr 2015 17:03:41 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> Message-ID: <554100DD.3080000@gmail.com> On 04/29/2015 09:06 AM, Alan Gauld wrote: > In principle its an acceptable strategy. A close alternative > would be to name the queries as explicit class variables. > So for example you would use: > > cur.execute(self.find_phone_query,(....)) > > Its less typing and less error prone in that you get a > syntax error on mistyping rather than a run time exception. > That's what I had initially but I used dictionaries for regexes I match the messages against to determine the type, I thought I'd organize stuff of the same nature together in a dictionary. JUNK = 'JUNK' RE_TYPE = { 'TYPE1' : re.compile(r'xxx'), 'TYPE2' : re.compile(r'yyy'), ... 'TYPEn' : re.compile(r'aaa'), } Then to get the type of the message, I just have to do: gen = (k for k in self.RE_TYPE if RE_TYPE[k].findall(msg_text)) msg_type = next(gen, self.JUNK) >> - Methods closed the connection themselves, so I used `with` in >> `init_db` instead of `try`, as it would close the connection >> automatically and rollback (I hope I'm not making this up). > > Try/except and with do different things but in this case > you can get away with it. The only loss is that your errors > here are not formatted in the same way as the other messages. I wrote it to do one specific job that's to be followed by some other task that _would_ raise an exception. Maybe it's lazy and am relying on the methods that call `init_db` to deal with the error. `init_db` just returns a connection and a cursor.. If the file didn't exist, it'd be created but without schema, the calling method (like `create` or `find` _will_, however produce an error as it tries to read/write. > Consider using docstrings rather than comments to describe the method > I see you do that below... Roger that. >> (__, cursor) = self.init_db() > > Don't use the __ 'variable' here, be explicit, it makes > maintenance much easier. > I actually searched specifically for something like this. In MATLAB, there's the ~ that does this. I'm not trying to write Python in a MATLAB style, but I was glad I found it here: http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable I was only interested in the cursor in that method. `init_db` returned only a connection in the beginning, but I didn't want to write conn.cursor every time. >> try: >> cursor.execute( >> self.QUERIES['FIND_PHONE'], >> (self.phone,) >> ) >> found = cursor.fetchone() >> return True if found else False >> except Exception as e: >> return self.ERROR.format(e.args[0]) > > Don't catch Exception, it's too wide. Catch the > actual errors that might arise, be as specific as possible. Thanks for bringing that to my attention. > >> def create(self, seed_balance): >> ''' Create a database entry for the sender.''' >> >> conn, cursor = self.init_db() >> try: >> cursor.execute( >> self.QUERIES['CREATE'], >> (self.phone, seed_balance) >> ) >> conn.commit() >> except Exception as e: >> return self.ERROR.format(e.args[0]) > > > as above > > Thank you for the feedback, Alan. -- ~Jugurtha Hadjar, From diliupg at gmail.com Wed Apr 29 10:03:11 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Wed, 29 Apr 2015 13:33:11 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> Message-ID: Thank you Alan. Understood. I already knew that. My question is How to to do it the second way. some code = what? My question is, how does one arrive at the code to put in place of "some code"? The code I used does not work correctly. The code is in this chain of email. I hope I am clear in what I am trying to do. On Wed, Apr 29, 2015 at 1:18 PM, Alan Gauld wrote: > On 29/04/15 08:15, diliup gabadamudalige wrote: > > 1. x = some code >> >> That is what I used and it worked. I was trying to find how we can do the >> same thing by updating the current position by doing >> >> 2. x += some code >> Above 1 works. 2 does not. Why is that? >> > > > Because they do completely different things! > > 1 is simply > > x = some code > > 2 is > > x = x + some code > > In 2 you are adding x to some code. > > Of course they don't work the same. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** From diliupg at gmail.com Wed Apr 29 10:13:49 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Wed, 29 Apr 2015 13:43:49 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> Message-ID: question to Lucas. Not sure if this is what you're looking for, but I would also use cos for the x coordinate as suggested. If: self.rect.x = self.radius * math.cos(self.angle) + self.center_x self.rect.y = self.radius * math.sin(self.angle) + self.center_y Take a derivative (assume: angle += angular_vel * dt for every increment in time dt), so that: self.rect.x += -self.radius * math.sin(self.angle) * self.angular_vel * dt self.rect.y += self.radius * math.cos(self.angle) * self.angular_vel * dt what is dt? On Wed, Apr 29, 2015 at 12:45 PM, diliup gabadamudalige wrote: > Thanks all for the responses. > Charles Coss? - yes I can write a simple pygame program that makes a > sprite move in a circle but it may not be the style and order that many may > approve or accept. I consider myself a student. :) > No one has pointed out why the object moves in a circle properly in the > bit of code where it is addressed directly and why it does not when the > same code is applied thru a class. > I know that an object can be made to move around the circumference of a > circle by constantly calculating the point and giving the x and y values > > 1. x = some code > > That is what I used and it worked. I was trying to find how we can do the > same thing by updating the current position by doing > > 2. x += some code > Above 1 works. 2 does not. Why is that? > > Both the same code. The same variable is used with different names cause > some others were confused when they were the same. > > I hope this time I have answered correctly. No more attachments. (e mail > or otherwise. :) ) > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** From diliupg at gmail.com Wed Apr 29 11:15:00 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Wed, 29 Apr 2015 14:45:00 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: <554095BF.2000208@btinternet.com> References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> Message-ID: x=42 good x += 42 -x ? That does not go by a mile of what I asked. Alan, are you telling me that there is no way that one can arrive at X2 which is the NEXT place that X1 will be after "some increment"? old x position = X1 new x position= X1 + some increment value which can be written as :new X = oldX + some increment value which can be simplified to X += some increment value? my orginal question was *Why does the object NOT move in a circle when implemented as a class?* All the code was provided. The above is what I asked. (I hope this is clear enough) On Wed, Apr 29, 2015 at 1:56 PM, Alan Gauld wrote: > On 29/04/15 09:03, diliup gabadamudalige wrote: > >> Thank you Alan. Understood. I already knew that. My question is >> >> How to to do it the second way. >> some code = what? >> >> The point is you cannot do it. > The second approach always uses the current value of x. > The first approach may or may not use the current value > of x. If it does not use x then the += style cannot be > made to work (unless you tag a -x on at the end! > > x = 42 > > x += 42-x > > Which is just stupid. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** From alan.gauld at btinternet.com Wed Apr 29 18:30:33 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 17:30:33 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> Message-ID: On 29/04/15 10:15, diliup gabadamudalige wrote: > x=42 good > x += 42 -x ? > > That does not go by a mile of what I asked. You've asked three different things: 1) Why the += form gives different results from the assignment form, 2) Why some code you apparently wriotre worked outside a class but not in a class 3) A specific question about some code for moving an object in PyGame around in a circle Number 1 is the only one I can comment on as I can't see your attachments. That is what I (and several others) have answered. They are fundamentally different. There is no general way to make an augmented assignment such that x = f(y) and x += f(y) (or even g(y)) produce the same result except by the trivial x += g(y) - x > Alan, are you telling me that there is no way that one can arrive at X2 > which is the NEXT place that X1 will be after "some increment"? > old x position = X1 No, that is a completely separate question and has nothing to do with using augmented assignment. But it does depend on the specifics of the situation and is mainly a mathematical problem rather than a Python one.. > new x position= X1 + some increment value > which can be written as :new X = oldX + some increment value > > which can be simplified to X += some increment value? That may or may not be possible, it depends on what the original equation in the pure assignment model is. > my orginal question was > > *Why does the object NOT move in a circle when implemented as a class?* Your original question was: is there a way to do self.rect.x +*= some value* self.rect.y += some value rather than self.rect.x = self.radius * math.sin(self.angle) + self.center_x self.rect.y = self.radius * math.cos(self.angle) + self.center_y Which is about the use of augmented assignment. > All the code was provided. No it wasn't. I have not seen any of your code because you persist in sending it as attachments which (as you've been told) do not work reliably in a text based mailing list. If you want comments on the code either post it inline in your message or as a link to a web site where we can all see it. > The above is what I asked. (I hope this is clear enough) Your class based code should work but without sight of it I cannot begin to guess about that aspect of your problem. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Wed Apr 29 18:43:19 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 17:43:19 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: <554100DD.3080000@gmail.com> References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: On 29/04/15 17:03, Jugurtha Hadjar wrote: >>> (__, cursor) = self.init_db() >> >> Don't use the __ 'variable' here, be explicit, it makes >> maintenance much easier. >> > > I actually searched specifically for something like this. In MATLAB, > there's the ~ that does this. I'm not trying to write Python in a MATLAB > style, but I was glad I found it here: > > http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable I've seen this before and strongly disagree with it. I suspect the author has never had to run a major maintenance project! A single underscore is, I agree, far worse that a dunder symbol but both are a maintenance nightmare. They are ambiguous, difficult to remember, easy to overlook and if you change your mind and decide you need to use it later it's a whole new name to go back and introduce (or worse be tempted to use the meaningless symbol). And if you need another 'throw-away' name later you use the same one, then forget there are two uses and try to use it anyway (even in debugging) and get completely wrong values, that may or may not look different to what you expect. (looking different is good - you can detect it easily, looking similar is very, very, bad!)... its just a horror story waiting to trip you up. It's far better to have a short meaningful name that is never used than a bland, meaningless, generic symbol. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From fomcl at yahoo.com Wed Apr 29 18:54:11 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 29 Apr 2015 09:54:11 -0700 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths Message-ID: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> ----------------------------- On Wed, Apr 29, 2015 4:11 PM CEST Peter Otten wrote: >Albert-Jan Roskam wrote: > >> Hello, >> >> Windows has the 'feature' that the CD command does not work with UNC >> paths. So in the code below, I cannot use the 'cwd' parameter of >> subprocess.Popen. Therefore I use pushd/popd to accomplish the same >> effect. Is there a better way to do this? (other than using full path >> names everywhere, or os.chdir). Would it be a useful improvement of Python >> itself if cwd also works with UNC path? > >What is the error you get? I don't have Windows to verify, but a quick look >into the subprocess source suggests that it uses CreateProcess(). >Googling for that finds > > > >which states > >"" >lpCurrentDirectory [in, optional] >The full path to the current directory for the process. The string can also >specify a UNC path. >"" Hmmm, that sounds pretty convincing indeed (makes it even stranger that CD works the way it works). I believe it threw a WindowsError, indicating that the file(s) could not be found, because the dir was not changed. I actually first ran into this problem with this script, so with my current script I immediately refrained from using cwd: http://code.activestate.com/recipes/578883-git-pre-commit-hook-to-reject-large-files-using-py/ Git gave a fatal error in windows and the pushd/popd fixed it. >> import sys >> import os >> import getpass >> import subprocess >> >> path = r'\\server\share\possibly with\space' >> executable = 'blah.exe' >> username = os.getenv("USERNAME") >> password = getpass.getpass("Enter password: ") >> infile = sys.argv[1] >> outfile = sys.argv[2] >> cmds = ['pushd "%s" &&' % path, executable, username, password, infile, >> outfile, "&& popd"] >> >> result = subprocess.Popen(" ".join(cmds), shell=True) >> error = result.stderr >> if error: >> raise RuntimeError(error.read()) >> >> Regards, >> >> Albert-Jan >> >> PS: Python 2.7 on Windows 7 32 From fomcl at yahoo.com Wed Apr 29 19:04:41 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 29 Apr 2015 10:04:41 -0700 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? Message-ID: <1430327081.72982.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> ------------------------------ On Wed, Apr 29, 2015 4:21 PM CEST boB Stepp wrote: >I now have Git installed on my Windows 7 PC at work. The files that I >wish to put under Git version control exist on a Solaris 10 >workstation. In the Git bash provided, I can ssh into the Solaris 10 >machine. I also can the CuteFTP program on my Windows PC to >move/copy/etc. files between the two machines. How can I put these >Solaris files under version control under these circumstances? I >thought I had conceptually seen how to accomplish this via ssh, but if >it is doable, my limited knowledge of Git and ssh is insufficient to >find the path of success. Uhmm, I'd (1) open a Github or Bitbucket account (2) ssh to the solaris machine (3) install git if needed (4) clone your repo (which has just the readme file at this point) (5) fill the local files, git add what you want to track, the git commit and git push. (6) in windows you can use msysgit to connect to your remote repo. But uhhm, this is not Python at all ;-) Albert-Jan From robertvstepp at gmail.com Wed Apr 29 19:12:43 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 12:12:43 -0500 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: <1430327081.72982.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> References: <1430327081.72982.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On Wed, Apr 29, 2015 at 12:04 PM, Albert-Jan Roskam wrote: > > ------------------------------ > On Wed, Apr 29, 2015 4:21 PM CEST boB Stepp wrote: > >>I now have Git installed on my Windows 7 PC at work. The files that I >>wish to put under Git version control exist on a Solaris 10 >>workstation. In the Git bash provided, I can ssh into the Solaris 10 >>machine. I also can the CuteFTP program on my Windows PC to >>move/copy/etc. files between the two machines. How can I put these >>Solaris files under version control under these circumstances? I >>thought I had conceptually seen how to accomplish this via ssh, but if >>it is doable, my limited knowledge of Git and ssh is insufficient to >>find the path of success. > > > ... (3) install git if needed ... It seems Git is needed, but I am not allowed to install it on the Solaris workstation. So is there a way around this? > > But uhhm, this is not Python at all ;-) I was hoping for clemency on this point due to the earlier thread(s) I started (Which included Python's unittest module.). -- boB From alan.gauld at btinternet.com Wed Apr 29 19:38:35 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 18:38:35 +0100 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: References: <1430327081.72982.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On 29/04/15 18:12, boB Stepp wrote: >> But uhhm, this is not Python at all ;-) > > I was hoping for clemency on this point due to the earlier thread(s) I > started (Which included Python's unittest module.). I've been blurring the lines on this one because version control is something everyone should do whether using Python or not and as a "beginners" list it seems fair to cover generic VC principles even in a specific thread on Git. But to be fair your specific set up is very unusual and it might be better to take it to a git specific forum for detailed resolution. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From lac at openend.se Wed Apr 29 19:52:33 2015 From: lac at openend.se (Laura Creighton) Date: Wed, 29 Apr 2015 19:52:33 +0200 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: Message from boB Stepp of "Wed, 29 Apr 2015 09:21:39 -0500." References: Message-ID: <201504291752.t3THqX5d018344@fido.openend.se> Glad things are going better. Next step. Can you get git running on your solaris machines? Easiest is if it is already installed .... or if the powers that be will install it for you. But if not, you ought to be able to build your own git from source and run it on your Solaris machines. This link http://joemaller.com/908/how-to-install-git-on-a-shared-host/ is a discription of how somebody did it for Fedora linux. However, if you run into trouble trying to do this, you need to talk to somebody who knows how gcc works on solaris, and where all the dependencies are, and what whatever error messages you are getting mean. Ideally you would have somebody who knows about git, too. That person isn't me. And I don't think that the python-tutor mailing list is the optimal place to look for such a person. I'd try some solaris list. Make sure that whoever you talk to knows that you don't have root access which is why you are building git from source in the first place, and gets a copy of exactly what you typed when you tried to build it, and exactly what you got back in terms of error messages, and output, pasted in, and not a summary of what you think that those error messages meant. Best of luck, Laura From fomcl at yahoo.com Wed Apr 29 21:24:37 2015 From: fomcl at yahoo.com (Albert-Jan Roskam) Date: Wed, 29 Apr 2015 19:24:37 +0000 (UTC) Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: References: Message-ID: <1398598326.361255.1430335477832.JavaMail.yahoo@mail.yahoo.com> ----- Original Message ----- > From: boB Stepp > To: tutor > Cc: > Sent: Wednesday, April 29, 2015 7:12 PM > Subject: Re: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? > > On Wed, Apr 29, 2015 at 12:04 PM, Albert-Jan Roskam > wrote: >> >> ------------------------------ >> On Wed, Apr 29, 2015 4:21 PM CEST boB Stepp wrote: >> >>> I now have Git installed on my Windows 7 PC at work. The files that I >>> wish to put under Git version control exist on a Solaris 10 >>> workstation. In the Git bash provided, I can ssh into the Solaris 10 >>> machine. I also can the CuteFTP program on my Windows PC to >>> move/copy/etc. files between the two machines. How can I put these >>> Solaris files under version control under these circumstances? I >>> thought I had conceptually seen how to accomplish this via ssh, but if >>> it is doable, my limited knowledge of Git and ssh is insufficient to >>> find the path of success. >> >> >> ... (3) install git if needed ... > > It seems Git is needed, but I am not allowed to install it on the > Solaris workstation. So is there a way around this? Ouch, that sucks. When I said "if needed", I meant "if not already there". Maybe somebody knows a smart solution with rsync or with ftp. Still, then you'd run your tests on Windows, but the code is for Solaris. >> But uhhm, this is not Python at all ;-) > > I was hoping for clemency on this point due to the earlier thread(s) I > started (Which included Python's unittest module.). I *love* Git (well, that sounds *very* geeky!) so I don't mind at all. Once you've got it running, you could install a commit hook that runs nosetests (or even tox). That's just two lines (a shebang and a call to once of those scripts) and then your unittests will be run automatically every time you do a git commit. Nice! From diliupg at gmail.com Wed Apr 29 20:37:05 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Thu, 30 Apr 2015 00:07:05 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> Message-ID: I do not understand how Alan does not get the code that is in this thread. Anyway I can conclude by saying that a friend of mine who is not in this thread solved the problem and I would like to share it with you. He has changed only a very smal portion in the original code that i posted in this thread. and it works perfectly. Apparently the problem is in the way the rect assignment is done in the Python/Pygame rect class. So as conclusion the code below works perfectly. No drifting. Class implemented. I hope everyone gets updated. Thanks for your time. import sys, os, pygame, itertools from math import sin,cos,pi from pygame.locals import * SCREENW = 800 SCREENH = 700 class object_factory(pygame.sprite.Sprite): def __init__(self, image, xpos = 0, ypos = 0): """Constructor""" pygame.sprite.Sprite.__init__(self) self.image = image self.mask = pygame.mask.from_surface(self.image) # pixelmask self.rect = self.image.get_rect() self.rect.x = xpos self.rect.y = ypos self.x=xpos self.y=ypos pygame.init() clock = pygame.time.Clock() os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50,50) #Set window position SCREEN = pygame.display.set_mode((SCREENW, SCREENH)) clock = pygame.time.Clock() pygame.display.set_caption('rotating object') ball = pygame.image.load("ball.jpg") pin=pygame.image.load("center.jpg"); platforms = pygame.sprite.Group() center_x = SCREENW/2 center_y = SCREENH/2 radius = 200 angle = pi/4 # starting angle 45 degrees omega = 0.1 #Angular velocity #--------------------------------------------------------------------------------------- for _ in itertools.repeat(None, 6): xpos = center_x + radius * cos(angle) #Starting position x ypos = center_y - radius * sin(angle) #Startinh position y obj = object_factory(ball, xpos, ypos) obj.angle = angle obj.omega = omega #angula velocity obj.radius = radius platforms.add(obj) angle += pi/3 #---------------------------------------------------------------------- while True: clock.tick(24) pygame.event.pump() keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): pygame.quit() sys.exit() SCREEN.fill((255,255,255)) SCREEN.blit(pin,(center_x, center_y)) #Class implementation-------------------------------------------------------------------------------------------------------------- for b in platforms: b.angle+=b.omega #Rect Base Rotation #b.rect.x += b.radius * b.omega * cos(b.angle + pi / 2) #b.rect.y -= b.radius * b.omega * sin(b.angle + pi / 2) #SCREEN.blit(ball,(b.rect.x,b.rect.y)) # Normal Rotation------------------------------------------------------------------------------------------------------------- b.x+=b.radius * b.omega * cos(b.angle + pi / 2) b.y-= b.radius * b.omega * sin(b.angle + pi / 2) SCREEN.blit(ball,(b.x,b.y)) pygame.display.update() On Wed, Apr 29, 2015 at 10:00 PM, Alan Gauld wrote: > On 29/04/15 10:15, diliup gabadamudalige wrote: > >> x=42 good >> x += 42 -x ? >> >> That does not go by a mile of what I asked. >> > > You've asked three different things: > > 1) Why the += form gives different results from the assignment form, > 2) Why some code you apparently wriotre worked outside a class > but not in a class > 3) A specific question about some code for moving an object > in PyGame around in a circle > > Number 1 is the only one I can comment on as I can't see your attachments. > That is what I (and several others) have answered. > They are fundamentally different. There is no general way > to make an augmented assignment such that > > x = f(y) and > x += f(y) (or even g(y)) > > produce the same result except by the trivial > > x += g(y) - x > > Alan, are you telling me that there is no way that one can arrive at X2 >> which is the NEXT place that X1 will be after "some increment"? >> old x position = X1 >> > > No, that is a completely separate question and has nothing > to do with using augmented assignment. But it does depend > on the specifics of the situation and is mainly a mathematical > problem rather than a Python one.. > > new x position= X1 + some increment value >> which can be written as :new X = oldX + some increment value >> >> which can be simplified to X += some increment value? >> > > That may or may not be possible, it depends on what the > original equation in the pure assignment model is. > > my orginal question was >> >> *Why does the object NOT move in a circle when implemented as a class?* >> > > Your original question was: > > is there a way to do > self.rect.x +*= some value* > self.rect.y += some value > > rather than > > self.rect.x = self.radius * math.sin(self.angle) + self.center_x > self.rect.y = self.radius * math.cos(self.angle) + self.center_y > > Which is about the use of augmented assignment. > > All the code was provided. >> > > No it wasn't. I have not seen any of your code because you persist > in sending it as attachments which (as you've been told) do not > work reliably in a text based mailing list. If you want > comments on the code either post it inline in your message > or as a link to a web site where we can all see it. > > The above is what I asked. (I hope this is clear enough) >> > > Your class based code should work but without sight of it > I cannot begin to guess about that aspect of your problem. > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** From robertvstepp at gmail.com Wed Apr 29 22:10:09 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 15:10:09 -0500 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? Message-ID: Python 2.4.4, Solaris 10. I have some functions that I believe I could collapse into a single function if I only knew how: def choose_compare(operator, value0, value1, pass_color, fail_color): """ Perform the comparison indicated by operator. Return pass_color if true, fail_color if false. """ if operator == '<': return less_than(value0, value1, pass_color, fail_color) elif operator == '<=': return less_than_or_equal(value0, value1, pass_color, fail_color) elif operator == '=': return equal(value0, value1, pass_color, fail_color) elif operator == '>': return greater_than(value0, value1, pass_color, fail_color) elif operator == '>=': return greater_than_or_equal(value0, value1, pass_color, fail_color) else: print 'WarningMessage = "Invalid comparison operator in function, choose_compare(). at Please contact script administrator for assistance.";' def less_than(value0, value1, pass_color, fail_color): """ See if value0 is less than value1. If true, return pass_color. If false, return fail_color. """ if value0 < value1: return pass_color, True else: return fail_color, False def less_than_or_equal(value0, value1, pass_color, fail_color): """ See if value0 is less than or equal to value1. If true, return pass_color. If false, return fail_color. """ if value0 <= value1: return pass_color, True else: return fail_color, False ... 3 more functions ... I won't give the remaining functions for the other comparison operators. The string variable, operator, is originally populated from a data file, which tells what type of comparison needs to be made. The last two functions I gave (and the ones I omitted giving) all follow the same exact pattern. I know there has to be some way to replace these 5 functions with 1, but what experimentation I have done to date has not worked. Also, what about the first function above? I could use 2 dictionaries, 1 for calling the 5 functions and one to pass the arguments, but is it worth doing this? Or, I would not be surprised if there is a much better way! ~(:>)) Thanks! -- boB From marc.tompkins at gmail.com Wed Apr 29 22:46:10 2015 From: marc.tompkins at gmail.com (Marc Tompkins) Date: Wed, 29 Apr 2015 13:46:10 -0700 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: References: Message-ID: On Wed, Apr 29, 2015 at 1:10 PM, boB Stepp wrote: > Python 2.4.4, Solaris 10. > > I have some functions that I believe I could collapse into a single > function if I only knew how: > > def choose_compare(operator, value0, value1, pass_color, fail_color): > """ > Perform the comparison indicated by operator. Return pass_color if > true, fail_color if false. > """ > if operator == '<': > return less_than(value0, value1, pass_color, fail_color) > elif operator == '<=': > return less_than_or_equal(value0, value1, pass_color, fail_color) > elif operator == '=': > return equal(value0, value1, pass_color, fail_color) > elif operator == '>': > return greater_than(value0, value1, pass_color, fail_color) > elif operator == '>=': > return greater_than_or_equal(value0, value1, pass_color, > fail_color) > else: > print 'WarningMessage = "Invalid comparison operator in > function, choose_compare(). at Please contact script administrator for > assistance.";' > > def less_than(value0, value1, pass_color, fail_color): > """ > See if value0 is less than value1. If true, return pass_color. If > false, return fail_color. > """ > if value0 < value1: > return pass_color, True > else: > return fail_color, False > > def less_than_or_equal(value0, value1, pass_color, fail_color): > """ > See if value0 is less than or equal to value1. If true, return > pass_color. If false, return fail_color. > """ > if value0 <= value1: > return pass_color, True > else: > return fail_color, False > > ... 3 more functions ... > > I won't give the remaining functions for the other comparison > operators. The string variable, operator, is originally populated from > a data file, which tells what type of comparison needs to be made. The > last two functions I gave (and the ones I omitted giving) all follow > the same exact pattern. I know there has to be some way to replace > these 5 functions with 1, but what experimentation I have done to date > has not worked. > > Also, what about the first function above? I could use 2 dictionaries, > 1 for calling the 5 functions and one to pass the arguments, but is it > worth doing this? Or, I would not be surprised if there is a much > better way! ~(:>)) > > Thanks! > Here's what I came up with: def choose_compare(operator, value0, value1, pass_color, fail_color): comps = {"=":"==", "<":"<", ">":">", "<=":"<=", ">=":">="} if operator in comps.keys(): operator = comps[operator] if eval("{} {} {}".format(value0, operator, value1)): return pass_color, True else: return fail_color, False else: print('WarningMessage') I would ordinarily avoid eval() like the plague, but I think that this sanitizes the input pretty effectively. I had to make comps a dict instead of a list because (in your example, anyway) you're using a single equals sign to check for equality, which throws a Syntax Error (e.g. "if 1 = 2" instead of "if 1 == 2"). From roel at roelschroeven.net Wed Apr 29 23:11:13 2015 From: roel at roelschroeven.net (Roel Schroeven) Date: Wed, 29 Apr 2015 23:11:13 +0200 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: Alan Gauld schreef op 2015-04-29 18:43: > On 29/04/15 17:03, Jugurtha Hadjar wrote: >> http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable > > I've seen this before and strongly disagree with it. I disagree with your disagreement. I'll try to explain. > They are ambiguous, difficult to remember, easy to overlook I'm not sure what exactly you mean by that. > and if you change your mind and decide you need to use it later > it's a whole new name to go back and introduce True, but I don't see how that is a problem. At that point the variable is only used at one point, so you only have to rename it at that one place. > (or worse be tempted to use the meaningless symbol). That would be bad indeed, but I think a very minimal amount of discipline is enough to avoid that. > And if you need another 'throw-away' name later you use the same one, then forget > here are two uses and try to use it anyway (even in debugging) and get > completely wrong values, that may or may not look different > to what you expect. The whole point of ignored variables is that you don't use them. If you use them, they're not exactly ignored variables. It doesn't matter if you use __ once or twice or many times more; all of them are to be ignored. > (looking different is good - you can > detect it easily, looking similar is very, very, bad!)... > its just a horror story waiting to trip you up. I'm not sure in what way __ can lead to horror stories. Do you have an example to fuel my imagination? > It's far better to have a short meaningful name that is never > used than a bland, meaningless, generic symbol. By 'short meaningful name', do you mean something like 'dummy' or 'ignorethis' as in basename, dummy, ext = filename.rpartition('.') or rather something like basename, separator, ext = filename.rpartition('.') In the first case, I prefer __ over dummy exactly because to me it's clearer at a glance that the name is one-use only and the value is to be ignored. In the second case, using a 'real' name like 'separator' means I now have to mentally keep track of it since as far as I can see at that point it might be used later in the code. To me, using _ or __ decreases the cognitive load because they tell me I don't have to remember anything about them, since they're not going to be used later. Read and forget. Best regards, Roel -- The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom. -- Isaac Asimov Roel Schroeven From robertvstepp at gmail.com Wed Apr 29 23:12:29 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 16:12:29 -0500 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: References: Message-ID: On Wed, Apr 29, 2015 at 3:46 PM, Marc Tompkins wrote: > On Wed, Apr 29, 2015 at 1:10 PM, boB Stepp wrote: >> >> Python 2.4.4, Solaris 10. >> >> I have some functions that I believe I could collapse into a single >> function if I only knew how: >> >> def choose_compare(operator, value0, value1, pass_color, fail_color): >> """ >> Perform the comparison indicated by operator. Return pass_color if >> true, fail_color if false. >> """ >> if operator == '<': >> return less_than(value0, value1, pass_color, fail_color) >> elif operator == '<=': >> return less_than_or_equal(value0, value1, pass_color, fail_color) >> elif operator == '=': >> return equal(value0, value1, pass_color, fail_color) >> elif operator == '>': >> return greater_than(value0, value1, pass_color, fail_color) >> elif operator == '>=': >> return greater_than_or_equal(value0, value1, pass_color, >> fail_color) >> else: >> print 'WarningMessage = "Invalid comparison operator in >> function, choose_compare(). at Please contact script administrator for >> assistance.";' >> >> def less_than(value0, value1, pass_color, fail_color): >> """ >> See if value0 is less than value1. If true, return pass_color. If >> false, return fail_color. >> """ >> if value0 < value1: >> return pass_color, True >> else: >> return fail_color, False >> >> def less_than_or_equal(value0, value1, pass_color, fail_color): >> """ >> See if value0 is less than or equal to value1. If true, return >> pass_color. If false, return fail_color. >> """ >> if value0 <= value1: >> return pass_color, True >> else: >> return fail_color, False >> >> ... 3 more functions ... >> >> I won't give the remaining functions for the other comparison >> operators. The string variable, operator, is originally populated from >> a data file, which tells what type of comparison needs to be made. The >> last two functions I gave (and the ones I omitted giving) all follow >> the same exact pattern. I know there has to be some way to replace >> these 5 functions with 1, but what experimentation I have done to date >> has not worked. >> >> Also, what about the first function above? I could use 2 dictionaries, >> 1 for calling the 5 functions and one to pass the arguments, but is it >> worth doing this? Or, I would not be surprised if there is a much >> better way! ~(:>)) >> >> Thanks! > > > Here's what I came up with: > > def choose_compare(operator, value0, value1, pass_color, fail_color): > comps = {"=":"==", "<":"<", ">":">", "<=":"<=", ">=":">="} > if operator in comps.keys(): > operator = comps[operator] > if eval("{} {} {}".format(value0, operator, value1)): > return pass_color, True > else: > return fail_color, False > else: > print('WarningMessage') > > I would ordinarily avoid eval() like the plague, but I think that this > sanitizes the input pretty effectively. I had to make comps a dict instead > of a list because (in your example, anyway) you're using a single equals > sign to check for equality, which throws a Syntax Error (e.g. "if 1 = 2" > instead of "if 1 == 2"). I could deal with the "=" issue by either reformatting my data file to use "==" in place of "=", or when I parse the data file, do the replacement there. A list instead of the dictionary looks a little easier on my eyes. The list has me so leery of eval and exec that I totally forgot about this possibility! There are only two places in my program where I read information directly into my program: 1) The data file, or 2) how the user of the planning software names his regions of interest (ROI) in the planning system software. I will reexamine my checks of (1). For (2) the planning software already has its own checks, which would filter out a lot. And I am checking the ROIs to see if they are present in the data file *exactly* as given in the data file; otherwise, I reject them. So I have stumbled (With your gracious help!) into a legitimate use of eval()? Many thanks, again! -- boB From robertvstepp at gmail.com Wed Apr 29 23:16:01 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 16:16:01 -0500 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: <201504292050.t3TKo7e7024322@fido.openend.se> References: <201504292050.t3TKo7e7024322@fido.openend.se> Message-ID: On Wed, Apr 29, 2015 at 3:50 PM, Laura Creighton wrote: > I forget. You are writing these things as functions rather than > methods of a class, because you don't know how to use classes yet? You forget nothing! ~(:>)) > Because you are absolutely correct that there are ways to simplify this, > but if you don't know how to use classes yet, put this on hold until > you do. And this particular thing you want to do is not the optimal > place to start learning about how to use classes. Since the unittest module creating test classes, I have commenced formal studying of this topic. But as you point out, not ready for it yet! -- boB From breamoreboy at yahoo.co.uk Wed Apr 29 23:42:40 2015 From: breamoreboy at yahoo.co.uk (Mark Lawrence) Date: Wed, 29 Apr 2015 22:42:40 +0100 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: References: Message-ID: On 29/04/2015 21:10, boB Stepp wrote: > Python 2.4.4, Solaris 10. > > I have some functions that I believe I could collapse into a single > function if I only knew how: > > def choose_compare(operator, value0, value1, pass_color, fail_color): > """ > Perform the comparison indicated by operator. Return pass_color if > true, fail_color if false. > """ > if operator == '<': > return less_than(value0, value1, pass_color, fail_color) > elif operator == '<=': > return less_than_or_equal(value0, value1, pass_color, fail_color) > elif operator == '=': > return equal(value0, value1, pass_color, fail_color) > elif operator == '>': > return greater_than(value0, value1, pass_color, fail_color) > elif operator == '>=': > return greater_than_or_equal(value0, value1, pass_color, fail_color) > else: > print 'WarningMessage = "Invalid comparison operator in > function, choose_compare(). at Please contact script administrator for > assistance.";' > > def less_than(value0, value1, pass_color, fail_color): > """ > See if value0 is less than value1. If true, return pass_color. If > false, return fail_color. > """ > if value0 < value1: > return pass_color, True > else: > return fail_color, False > > def less_than_or_equal(value0, value1, pass_color, fail_color): > """ > See if value0 is less than or equal to value1. If true, return > pass_color. If false, return fail_color. > """ > if value0 <= value1: > return pass_color, True > else: > return fail_color, False > > ... 3 more functions ... > > I won't give the remaining functions for the other comparison > operators. The string variable, operator, is originally populated from > a data file, which tells what type of comparison needs to be made. The > last two functions I gave (and the ones I omitted giving) all follow > the same exact pattern. I know there has to be some way to replace > these 5 functions with 1, but what experimentation I have done to date > has not worked. > > Also, what about the first function above? I could use 2 dictionaries, > 1 for calling the 5 functions and one to pass the arguments, but is it > worth doing this? Or, I would not be surprised if there is a much > better way! ~(:>)) > > Thanks! > This isn't a job for Bicycle Repair Man!!! It smacks to me of dictionaries and the operator module but I'm too bone idle to look it up myself, so try here https://docs.python.org/3/library/operator.html D'oh :) -- My fellow Pythonistas, ask not what our language can do for you, ask what you can do for our language. Mark Lawrence From jugurtha.hadjar at gmail.com Wed Apr 29 23:52:16 2015 From: jugurtha.hadjar at gmail.com (Jugurtha Hadjar) Date: Wed, 29 Apr 2015 22:52:16 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> Message-ID: <55415290.6080907@gmail.com> On 04/29/2015 09:50 AM, Peter Otten wrote: > > My random observations: > > (1) find() and create() look very similar. Try hard to factor out common > code. You might even combine it into a single method ensure_balance(phone). > I'll think about it. I can't see for now how I would combine the two (each are triggered by different sets of conditions), but there's probably a better way. > (2) According to > > https://docs.python.org/dev/library/sqlite3.html#using-the-connection-as-a-context-manager > > - the context manager automatically commits > - you can run sql directly on the connection > I read that but I can't recall for the life of me why I didn't use it that way. Maybe I didn't understand it well or something broke, etc. I'll look into it. > It might by a good idea to refactor init_db() to just return the connection > and then use it as > > with self.init_db() as conn: > return conn.execute( > self.QUERIES['FIND_PHONE'], > (self.phone,)).fetchone() is not None > > If you need a cursor you can easily get one from the connection. If you want > more complex handling later you can always turn init_db() into a > contextmanager (see > > ). > Yes, that's the way it was but I didn't like conn.cursor and I didn't know how to use context managers (still don't). So I wanted to have something working first, and then improving it now. > (3) Catching Exception is overly broad. You will also catch a typo like > > cursor.execute( > self.QUERIES['CERATE'], > (self.phone, seed_balance) > ) > > where the proper fix is to modify the script. Only catch exceptions that you > can actually handle. Example: a table doesn't exist, and you want to create > it lazily on first access. Let all other exceptions just bubble up. It may > seem lazy, but a complete traceback is invaluable for identifying and fixing > a bug. > Right. This was also pointed by Alan so it must be really shabby. I'll look into it. > (4) self.ERROR.format(e.args[0]) > > is probably a string with len() > 0, and thus True in a boolean context. > From that follows an exception in the find() method in > >> self.known = self.find() > > causes the following if-suite to be run > >> if self.known: >> self.balance = self.get_balance() > > and if get_balance() has a same idea of proper exception handling > > self.balance will end up containing an error message. Nice, really nice :) > > (5) From point (4) I conclude that you don't have unit tests that cover your > code. You should really write some of these before pondering about stylistic > issues. Unit tests > > - help avoid errors > - make changes in the code less of a gamble because if the tests succeed > after the change you can be confident the change didn't introduce an error > - what you might not expect: how drastically tests affect the style of your > code. You'll see yourself thinking "How can I test that?" with every line of > code that you write, and that alone will improve the quality of your code. > I have simple scripts that test for specific things, but it's not really professional neither does it follow any structure, etc. I'll improve the code following the recommendations on this thread.. Thanks, Peter. -- ~Jugurtha Hadjar, From diliupg at gmail.com Wed Apr 29 22:19:59 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Thu, 30 Apr 2015 01:49:59 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: <55412921.3050506@btinternet.com> References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> <55412921.3050506@btinternet.com> Message-ID: Thanks Alan. It is partly due to curiosity but I also wanted to have a common update method. And as I almost always use the x+= some code, y+=some code for animation stuff I wanted to know how it could be done using this method rather than finding each position separately and assigning with x= some code, y = some code (new position). But here is STILL something curious in this whole matter. If I update the rect positions with obj.rect.x+ = some code obj.rect.y+ = some code then the rotation are NOT circular. BUT if I use obj.x += some code obj.y += some code and then do obj.rect.x, obj.rect.y = obj.x, obj.y then the rotation works correct!! This is really weird and I have no explanation as to why this happens!!! Can you or anyone else explain this strange behaviour? After all a position is a position.(at least that;s how I understand as long as you stick with the same coordinate through out.) The code is below. import sys, os, pygame, itertools from math import sin,cos,pi from pygame.locals import * SCREENW = 800 SCREENH = 700 class object_factory(pygame.sprite.Sprite): def __init__(self, image, xpos = 0, ypos = 0): """Constructor""" pygame.sprite.Sprite.__init__(self) self.image = image self.mask = pygame.mask.from_surface(self.image) # pixelmask self.rect = self.image.get_rect() self.rect.x = xpos self.rect.y = ypos self.x=xpos self.y=ypos pygame.init() clock = pygame.time.Clock() os.environ['SDL_VIDEO_WINDOW_POS'] = "%d,%d" % (50,50) #Set window position SCREEN = pygame.display.set_mode((SCREENW, SCREENH)) clock = pygame.time.Clock() pygame.display.set_caption('rotating object') ball = pygame.image.load("ball.jpg") pin=pygame.image.load("center.jpg"); platforms = pygame.sprite.Group() center_x = SCREENW/2 center_y = SCREENH/2 radius = 200 angle = pi/4 # starting angle 45 degrees omega = 0.1 #Angular velocity for _ in itertools.repeat(None, 6): xpos = center_x + radius * cos(angle) #Starting position x ypos = center_y - radius * sin(angle) #Startinh position y obj = object_factory(ball, xpos, ypos) obj.angle = angle obj.omega = omega #angula velocity obj.radius = radius platforms.add(obj) angle += pi/.5 #---------------------------------------------------------------------- while True: clock.tick(24) pygame.event.pump() keys = pygame.key.get_pressed() for event in pygame.event.get(): if event.type == QUIT or (event.type == KEYDOWN and event.key == K_ESCAPE): pygame.quit() sys.exit() SCREEN.fill((0, 0, 0)) SCREEN.blit(pin,(center_x - pin.get_width() / 2, center_y - pin.get_height() / 2)) pygame.draw.circle(SCREEN, (0, 0, 255), (center_x, center_y), radius, 2) for b in platforms: b.angle+=b.omega #Rect Base Rotation #b.rect.x += b.radius * b.omega * cos(b.angle + pi / 2) #b.rect.y -= b.radius * b.omega * sin(b.angle + pi / 2) #SCREEN.blit(ball,(b.rect.x,b.rect.y)) #Normal Rotation b.x+= b.radius * b.omega * cos(b.angle + pi / 2) b.y-= b.radius * b.omega * sin(b.angle + pi / 2) b.rect.x, b.rect.y = b.x - b.rect.width / 2, b.y - b.rect.height / 2 #SCREEN.blit(ball,(b.x,b.y)) # this and the line below gives the same result #SCREEN.blit(ball, (b.rect.x, b.rect.y)) platforms.update() platforms.draw(SCREEN) pygame.time.wait(100) pygame.display.update() On Thu, Apr 30, 2015 at 12:25 AM, Alan Gauld wrote: > On 29/04/15 19:37, diliup gabadamudalige wrote: > >> I do not understand how Alan does not get the code >> > > > Replying off list. > > I don't get it because text based email systems often strip out attachments > since they are a security risk. As the name says they are *text* based. > > However, now that I've seen it and I see your solution I can better > understand > what you were trying to ask, which was the solution to a very specific > scenario. > > I'm still not sure why you wanted to use augmented assignment, other > than curiosity perhaps, but at least I now see what you were trying to do. > Thanks for posting the solution. > > > -- > Alan G > Author of the Learn to Program web site > http://www.alan-g.me.uk/ > http://www.amazon.com/author/alan_gauld > Follow my photo-blog on Flickr at: > http://www.flickr.com/photos/alangauldphotos > > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** From lac at openend.se Wed Apr 29 22:50:07 2015 From: lac at openend.se (Laura Creighton) Date: Wed, 29 Apr 2015 22:50:07 +0200 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: Message from boB Stepp of "Wed, 29 Apr 2015 15:10:09 -0500." References: Message-ID: <201504292050.t3TKo7e7024322@fido.openend.se> I forget. You are writing these things as functions rather than methods of a class, because you don't know how to use classes yet? Because you are absolutely correct that there are ways to simplify this, but if you don't know how to use classes yet, put this on hold until you do. And this particular thing you want to do is not the optimal place to start learning about how to use classes. Laura From dyoo at hashcollision.org Thu Apr 30 00:10:00 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Wed, 29 Apr 2015 15:10:00 -0700 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> Message-ID: On Wed, Apr 29, 2015 at 11:37 AM, diliup gabadamudalige wrote: > I do not understand how Alan does not get the code that is in this thread. Hi Dilliup, Please try to avoid using the phrase, "I don't understand how does not get ...". You might not realize it, but it's radioactive: it's has a very negative connotation that is toxic to collaborative communities. For more information on this, there's a very good book called Team Geek that talks about these issues: https://books.google.com/books/about/Team_Geek.html?id=Iwk_pKeBc9gC&hl=en Also see Hacker School's Social Rules: https://www.recurse.com/manual#sub-sec-social-rules Thanks! From alan.gauld at btinternet.com Thu Apr 30 00:21:08 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 23:21:08 +0100 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> <55412921.3050506@btinternet.com> Message-ID: On 29/04/15 21:19, diliup gabadamudalige wrote: > It is partly due to curiosity but I also wanted to have a common update > method. And as I almost always use the x+= some code, y+=some code for > animation stuff I wanted to know how it could be done using this method > rather than finding each position separately and assigning with x= some > code, y = some code (new position). OK, Curiosity is good. But the conversion is mainly a math challenge rather than a programming one. And its a very seductive but dangerous mind set to try to force a problem into a pattern that fits how you usually do it. Especially if the transformed code looks less intuitive than the original. When I started in Python it didn't even have the += style of augmented assignment, it was mainly introduced to save some typing, nothing more. Remember that += is still an assignment to x. It is not significantly different or in any way 'better' than the standard assignment. In languages like C '+=' (and even more so '++' which doesn't exist in Python) used to result in performance improvements but optimising compilers have removed even that reason for using it. Now it should just be considered a typing shortcut. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From __peter__ at web.de Thu Apr 30 00:32:57 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 30 Apr 2015 00:32:57 +0200 Subject: [Tutor] Good name(s) for to-be-ignored variables, was Re: Good Taste Question: Using SQLite3 in Python References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: Roel Schroeven wrote: > Alan Gauld schreef op 2015-04-29 18:43: >> On 29/04/15 17:03, Jugurtha Hadjar wrote: >>> http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable >> >> I've seen this before and strongly disagree with it. > > I disagree with your disagreement. I'll try to explain. > >> They are ambiguous, difficult to remember, easy to overlook > > I'm not sure what exactly you mean by that. > >> and if you change your mind and decide you need to use it later > > it's a whole new name to go back and introduce > > True, but I don't see how that is a problem. At that point the variable > is only used at one point, so you only have to rename it at that one > place. > >> (or worse be tempted to use the meaningless symbol). > > That would be bad indeed, but I think a very minimal amount of > discipline is enough to avoid that. > >> And if you need another 'throw-away' name later you use the same one, >> then forget > > here are two uses and try to use it anyway (even in debugging) and get >> completely wrong values, that may or may not look different >> to what you expect. > > The whole point of ignored variables is that you don't use them. If you > use them, they're not exactly ignored variables. It doesn't matter if > you use __ once or twice or many times more; all of them are to be > ignored. > > > (looking different is good - you can > > detect it easily, looking similar is very, very, bad!)... > > its just a horror story waiting to trip you up. > > I'm not sure in what way __ can lead to horror stories. Do you have an > example to fuel my imagination? > > > It's far better to have a short meaningful name that is never > > used than a bland, meaningless, generic symbol. > > By 'short meaningful name', do you mean something like 'dummy' or > 'ignorethis' as in > > basename, dummy, ext = filename.rpartition('.') > > or rather something like > > basename, separator, ext = filename.rpartition('.') > > In the first case, I prefer __ over dummy exactly because to me it's > clearer at a glance that the name is one-use only and the value is to be > ignored. > In the second case, using a 'real' name like 'separator' means I now > have to mentally keep track of it since as far as I can see at that > point it might be used later in the code. > > > To me, using _ or __ decreases the cognitive load because they tell me I > don't have to remember anything about them, since they're not going to > be used later. Read and forget. Inside a function there's a middle ground, a leading underscore: def whatever(): ... basename, _extsep, ext = filename.rpartition(os.extsep) ... The name makes it clear what _extsep is supposed to contain, and the underscore indicates that you are not using the name. You can later question the decision that you are not interested in _extsep -- in the example you may decide that you want to discriminate between "somefile." and "somefile" Even if you stick with the original design I find it more readable to state explicitly what you are throwing away. My whatever() function is an example where the name of the to-be-ignored variable led to a change in the code: I started with _separator and then remembered that the separator need not be a dot. Admittedly I don't expect to use an OS where os.extsep != "." anytime soon, but you get the idea... From __peter__ at web.de Thu Apr 30 00:49:12 2015 From: __peter__ at web.de (Peter Otten) Date: Thu, 30 Apr 2015 00:49:12 +0200 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? References: Message-ID: boB Stepp wrote: > On Wed, Apr 29, 2015 at 3:46 PM, Marc Tompkins > wrote: >> On Wed, Apr 29, 2015 at 1:10 PM, boB Stepp >> wrote: >>> >>> Python 2.4.4, Solaris 10. >>> >>> I have some functions that I believe I could collapse into a single >>> function if I only knew how: >>> >>> def choose_compare(operator, value0, value1, pass_color, fail_color): >>> """ >>> Perform the comparison indicated by operator. Return pass_color if >>> true, fail_color if false. >>> """ >>> if operator == '<': >>> return less_than(value0, value1, pass_color, fail_color) >>> elif operator == '<=': >>> return less_than_or_equal(value0, value1, pass_color, >>> fail_color) >>> elif operator == '=': >>> return equal(value0, value1, pass_color, fail_color) >>> elif operator == '>': >>> return greater_than(value0, value1, pass_color, fail_color) >>> elif operator == '>=': >>> return greater_than_or_equal(value0, value1, pass_color, >>> fail_color) >>> else: >>> print 'WarningMessage = "Invalid comparison operator in >>> function, choose_compare(). at Please contact script administrator for >>> assistance.";' >>> >>> def less_than(value0, value1, pass_color, fail_color): >>> """ >>> See if value0 is less than value1. If true, return pass_color. If >>> false, return fail_color. >>> """ >>> if value0 < value1: >>> return pass_color, True >>> else: >>> return fail_color, False >>> >>> def less_than_or_equal(value0, value1, pass_color, fail_color): >>> """ >>> See if value0 is less than or equal to value1. If true, return >>> pass_color. If false, return fail_color. >>> """ >>> if value0 <= value1: >>> return pass_color, True >>> else: >>> return fail_color, False >>> >>> ... 3 more functions ... >>> >>> I won't give the remaining functions for the other comparison >>> operators. The string variable, operator, is originally populated from >>> a data file, which tells what type of comparison needs to be made. The >>> last two functions I gave (and the ones I omitted giving) all follow >>> the same exact pattern. I know there has to be some way to replace >>> these 5 functions with 1, but what experimentation I have done to date >>> has not worked. >>> >>> Also, what about the first function above? I could use 2 dictionaries, >>> 1 for calling the 5 functions and one to pass the arguments, but is it >>> worth doing this? Or, I would not be surprised if there is a much >>> better way! ~(:>)) >>> >>> Thanks! >> >> >> Here's what I came up with: >> >> def choose_compare(operator, value0, value1, pass_color, fail_color): >> comps = {"=":"==", "<":"<", ">":">", "<=":"<=", ">=":">="} >> if operator in comps.keys(): >> operator = comps[operator] >> if eval("{} {} {}".format(value0, operator, value1)): >> return pass_color, True >> else: >> return fail_color, False >> else: >> print('WarningMessage') >> >> I would ordinarily avoid eval() like the plague, but I think that this >> sanitizes the input pretty effectively. I had to make comps a dict >> instead of a list because (in your example, anyway) you're using a single >> equals >> sign to check for equality, which throws a Syntax Error (e.g. "if 1 = 2" >> instead of "if 1 == 2"). > > I could deal with the "=" issue by either reformatting my data file to > use "==" in place of "=", or when I parse the data file, do the > replacement there. A list instead of the dictionary looks a little > easier on my eyes. > > The list has me so leery of eval and exec that I totally forgot about > this possibility! There are only two places in my program where I read > information directly into my program: 1) The data file, or 2) how the > user of the planning software names his regions of interest (ROI) in > the planning system software. I will reexamine my checks of (1). For > (2) the planning software already has its own checks, which would > filter out a lot. And I am checking the ROIs to see if they are > present in the data file *exactly* as given in the data file; > otherwise, I reject them. > > So I have stumbled (With your gracious help!) into a legitimate use of > eval()? No. To expand on Marks hint here's how to do it without evil eval(). import operator comps = { "=": operator.eq, "<": operator.lt, ">": operator.gt, # ... } def choose_compare(operator, value0, value1, pass_color, fail_color): op = comps[operator] if op(value0, value1): return pass_color, True else: return fail_color, False print(choose_compare("=", 1, 1, "red", "blue")) print(choose_compare("<", 1, 2, "red", "blue")) print(choose_compare("<", 2, 1, "red", "blue")) Rule of thumb: when you think you need eval() you're wrong. From alan.gauld at btinternet.com Thu Apr 30 00:51:17 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Wed, 29 Apr 2015 23:51:17 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: On 29/04/15 22:11, Roel Schroeven wrote: > Alan Gauld schreef op 2015-04-29 18:43: >> On 29/04/15 17:03, Jugurtha Hadjar wrote: >>> http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable >>> >> >> I've seen this before and strongly disagree with it. > > I disagree with your disagreement. I'll try to explain. > >> They are ambiguous, difficult to remember, easy to overlook > > I'm not sure what exactly you mean by that. If something exists in a function, over time somebody will use it. Especially during debugging, priont is a dangerous tool in these cases. Simple fact of life. If it exists it should be visible (not too short or incongruous) Trying to visually scan for _ or even __ is hard. Also different fonts make _ and __ hard to distinguish. >> and if you change your mind and decide you need to use it later > > it's a whole new name to go back and introduce > > True, but I don't see how that is a problem. At that point the variable > is only used at one point, so you only have to rename it at that one place. It is if its only used once - see below. Renaming the wrong variable (especially ising search./replace in the editor) is a very common way to introduce new bugs into working code! Having spent nearly 10 years running 3 different maintenance teams I know how easy it is for new programmers(*) to start changing things they don;t understand, especially when under time pressure. (*)And maintenance teams are almost always comprised of a combination of new or very old (read jaded) programmers. The top players are reserved for the exciting new stuff! >> (or worse be tempted to use the meaningless symbol). > > That would be bad indeed, but I think a very minimal amount of > discipline is enough to avoid that. Its almost impossible, A maintenance team is usually working on a ratio of 10-50,000 lines of code per programmer per project and typically 3-5 projects. So if you have to hold 50-150,000 lines of code in mind its very easy to slip something in as a 'quick fix' intending to fix it next time then forget about it. Especially if you have to check in two bug fixes before you get to go home tonight.... Maintenance programmers are rarely the people who wrote the code, and they rarely have much personal pride invested in the code they have to fix. Even if they are the original developer they will have moved on to new projects and fixing 5 year old code is a low priority. Its all about human nature. > The whole point of ignored variables is that you don't use them. That's the point when they are created, but too often a use is found for these things. The original author is never in a position to say 'this will never be used in the future' that's just too idealistic. And the original author is very unlikely to be the long tem maintainer. Even in open-source where people tend to stick with projects for a few years its not true. In commercial code the author probably leaves the company within 6 months of writing the code. He may never even see it go into production... > use them, they're not exactly ignored variables. It doesn't matter if > you use __ once or twice or many times more; all of them are to be ignored. Absolutely. nothing can be guaranteed to be ignored over time, to start out with tat asumption is tom lay the seeds of chaos later. > > (looking different is good - you can > > detect it easily, looking similar is very, very, bad!)... > > its just a horror story waiting to trip you up. > > I'm not sure in what way __ can lead to horror stories. Do you have an > example to fuel my imagination? None in Python - I've never run a Python maintenance squad, but I have led assembler, C/C++, SQL, Perl and COBOL: teams. In every case there have been attempts to use variables that had been intended to be unused - in some cases randomly initialized/unassigned, reassigned etc. I once saw a C function with the same dummy variable use 4 times - although that did have a name, but it was a placeholder like x. But in Perl I've seen the infamous $_ abused many times (although that's slightly different since it magically takes on certain values, implicit rather than explicit) Python tries to avoid these things but the whole _/__ variable scheme is IMHO one of its worst features. > > It's far better to have a short meaningful name that is never > > used than a bland, meaningless, generic symbol. > > By 'short meaningful name', do you mean something like 'dummy' or > 'ignorethis' as in > > basename, dummy, ext = filename.rpartition('.') > > or rather something like > > basename, separator, ext = filename.rpartition('.') > The latter. or even 'sep' as shorter than 'separator'. At least it gives some clue to its meaning and can be used later if needed. Because its not expected to be used typing the few extra characters once doesn't hurt. But it makes scaffold code, debug code and extension code much easier to write. > In the first case, I prefer __ over dummy exactly because to me it's > clearer at a glance that the name is one-use only and the value is to be > ignored. The intent may be clearer but dummy is much easier to scan, search for and spot visually. > In the second case, using a 'real' name like 'separator' means I now > have to mentally keep track of it since as far as I can see at that > point it might be used later in the code. It will get reused anyhow, just accept that and give it a sensible name. If you don't intend to use it ignore it. > To me, using _ or __ decreases the cognitive load because they tell me I > don't have to remember anything about them, since they're not going to > be used later. Read and forget. But they will be. Almost for certain. It's human nature and the nature of code maintenance. If it's there somebody will find a use for it. The fact that 5 or 10 years earlier the author didn't intend for it to be used is immaterial. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From eryksun at gmail.com Thu Apr 30 01:12:34 2015 From: eryksun at gmail.com (eryksun) Date: Wed, 29 Apr 2015 18:12:34 -0500 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> References: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On Wed, Apr 29, 2015 at 11:54 AM, Albert-Jan Roskam wrote: > Hmmm, that sounds pretty convincing indeed (makes it even stranger that CD works the way it works). > I believe it threw a WindowsError, indicating that the file(s) could not be found, because the dir was > not changed. I actually first ran into this problem with this script, so with my current script I > immediately refrained from using cwd: > http://code.activestate.com/recipes/578883-git-pre-commit-hook-to-reject-large-files-using-py/ > Git gave a fatal error in windows and the pushd/popd fixed it. I don't see why you'd need shell=True. Windows supports UNC paths in the working directory, but the cmd.exe shell (being a crusty relic of the 1980s) does not. So just use the default value, shell=False. (However, on POSIX systems, unlike Windows, using shell=False requires `cmd` to be a list.) BTW, there's no need to explicitly pass cwd=os.getcwd(). The default behavior is to inherit the working directory of the current process. From dyoo at hashcollision.org Thu Apr 30 01:52:53 2015 From: dyoo at hashcollision.org (Danny Yoo) Date: Wed, 29 Apr 2015 16:52:53 -0700 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: References: Message-ID: Hi Bob, By the way, it sounds like you're starting to learn about how to write interpreters. If that's the case, you might find PLAI helpful: http://cs.brown.edu/~sk/Publications/Books/ProgLangs/ helpful. (Full disclosure: the author was my external advisor. :P) Another good book is EoPL: http://www.amazon.com/Essentials-Programming-Languages-Daniel-Friedman/dp/0262062798 I have fond memories of those two books. From alan.gauld at btinternet.com Thu Apr 30 02:08:13 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 30 Apr 2015 01:08:13 +0100 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: References: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On 30/04/15 00:12, eryksun wrote: > the working directory, but the cmd.exe shell (being a crusty relic of > the 1980s) does not. Actually cmd.exe is fine with UNC paths. It's only when you combine them with Windows /option style that it has issues but even then putting the path in quotes will usually do the trick. It's the old MS-DOS COMMAND.COM that can't cope. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From eryksun at gmail.com Thu Apr 30 02:48:19 2015 From: eryksun at gmail.com (eryksun) Date: Wed, 29 Apr 2015 19:48:19 -0500 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: References: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On Wed, Apr 29, 2015 at 7:08 PM, Alan Gauld wrote: > On 30/04/15 00:12, eryksun wrote: > >> the working directory, but the cmd.exe shell (being a crusty relic of >> the 1980s) does not. > > Actually cmd.exe is fine with UNC paths. It's only when you > combine them with Windows /option style that it has issues > but even then putting the path in quotes will usually do > the trick. > > It's the old MS-DOS COMMAND.COM that can't cope. cmd.exe was developed for OS/2 (1987) to replace COMMAND.COM (1981). cmd.exe cannot use a UNC path as the current directory. What it can do is `pushd` a UNC path, which mounts it as a drive letter. If you do try to start cmd.exe with a UNC path as the working directory, it instead sets the working directory to the Windows directory. For example: (test) C:\Temp>python Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:16:31) [MSC v.1600 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os, subprocess >>> os.chdir(r'\\127.0.0.1\C$') >>> subprocess.call('cmd') '\\127.0.0.1\C$' CMD.EXE was started with the above path as the current directory. UNC paths are not supported. Defaulting to Windows directory. Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. (test) C:\Windows> From cybervigilante at gmail.com Thu Apr 30 03:05:29 2015 From: cybervigilante at gmail.com (Jim Mooney Py3.4.3winXP) Date: Wed, 29 Apr 2015 18:05:29 -0700 Subject: [Tutor] raise exception works as planned in program but not when imported into testing module Message-ID: I raised an exception in the parse_string function in my math parser program, function_tosser.py, and caught it in the calling routine, and that worked fine. But when I imported function_tosser.py into a test program, tester.py, it threw the exception in the parse_string function instead of handling it in the try block in the calling routine. Why did it work in one and not the other? The testing program works fine if I return None as I did before, instead of raising the exception. # function_tosser.py """ Takes the name of a binary math operation and two numbers from input, repeatedly, and displays the results until done """ def add(a, b): return a + b def subtract(a, b): return b - a def minus(a, b): return a - b def multiply(a, b): return a * b def divide(a, b): return a / b operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract, 'subtracted': subtract, '-': minus, 'minus': minus, 'multiply': multiply, '*': multiply, 'multiplied': multiply, 'times': multiply, 'divide': divide, '/': divide, 'divided': divide} def test_number(astring): """ Input: A string that should represent a valid int or float. Output: An int or float on success. None on failure. """ for make_type in (int, float): try: return make_type(astring) except ValueError: # Previously returned None, which worked. This works fine here but when imported into the test program pass # it doesn't wait for the try block in the calling routine. return None def parse_string(math_string): """Input: A math string with a verbal or mathematical operation and two valid numbers to operate on. Extra numbers and operations are ignored. Output: A tuple containing a function corresponding to the operation and the two numbers. Returns None on failure. """ operation = None tokens = math_string.split() numbers = [] for token in tokens: if token in operations: operation = operations[token] elif test_number(token) != None: numbers.append(test_number(token)) if len(numbers) > 1: break if operation is None or len(numbers) < 2: raise ValueError else: return operation, numbers[0], numbers[1] if __name__ == "__main__": instructions = '''Enter two numbers and one of the four basid math operations, either mathematical or verbal. i.e. 3 + 2, 12 divided by 14, 10 minus 4, etc. Enter done to quit. ''' try: user_input = input(instructions) while True: if user_input == 'done': break try: result = parse_string(user_input) except ValueError: print("Not a valid math operation.") else: func, num1, num2 = result print(func(num1, num2)) user_input = input() except KeyboardInterrupt: print("Program terminated by user") # tester.py '''Test function_tosser.py mainlogic against random operators, operands, and bad input''' import random import function_tosser as ft valid_terms = list(ft.operations.keys()) def eval_test(): pass trash = ['1 +', 'blah', '3-4', 'gargle', 'Newt Gingrich', ",,,,,", '{+=-33.44 minus12 3 times blarg 1445641654644555455'] for ctr in range(50): term = ' ' + random.choice(valid_terms) + ' ' num1 = str(random.randint(1,1000)) num2 = str(random.randint(1,1000)) if term == ' subtract ' or term == ' subtracted ': term = ' subtracted from ' if ctr % 10 == 0: # stress testing for a None failure monkey_wrench = random.choice(trash) print(ft.parse_string(monkey_wrench), '\n') else: func, num1, num2 = ft.parse_string(num1 + term + num2) print(func, num1, term, num2) print('result:',func(num1, num2), '\n') -- Jim "What a rotten, failed experiment. I'll start over. Maybe dogs instead of monkeys this time." --God From eryksun at gmail.com Thu Apr 30 03:28:13 2015 From: eryksun at gmail.com (eryksun) Date: Wed, 29 Apr 2015 20:28:13 -0500 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: References: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On Wed, Apr 29, 2015 at 7:48 PM, eryksun wrote: > cmd.exe was developed for OS/2 (1987) to replace COMMAND.COM (1981). Actually, I stand corrected about the reason being cmd's 1980s crustiness. Per [KB156276][1] this check was added to NT 4.0 (1996) to address a vaguely described problem ("a UNC name may cause problems with child processes launched from such a console when that console is exited or halted"), which may not even be a problem nowadays (Windows 7+) since the console was moved out of CSRSS.EXE (the Windows session server) into instances of conhost.exe that run in the security context of the client. Try adding the registry setting to disable this check. Probably nothing bad will happen. Here's a reg.exe command to disable the check for the current user: reg add "HKCU\Software\Microsoft\Command Processor" /v DisableUNCCheck /t REG_DWORD /d 1 After disabling the check, my previous example should work fine: (test) C:\Temp>python Python 3.4.2 (v3.4.2:ab2c023a9432, Oct 6 2014, 22:16:31) [MSC v.1600 64 bit (AMD64)] on win32 Type "help", "copyright", "credits" or "license" for more information. >>> import os, subprocess >>> os.chdir(r'\\127.0.0.1\C$') >>> subprocess.call('cmd') Microsoft Windows [Version 6.1.7601] Copyright (c) 2009 Microsoft Corporation. All rights reserved. (test) \\127.0.0.1\C$> [1]: https://support.microsoft.com/en-us/kb/156276 From eryksun at gmail.com Thu Apr 30 03:50:57 2015 From: eryksun at gmail.com (eryksun) Date: Wed, 29 Apr 2015 20:50:57 -0500 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: References: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: On Wed, Apr 29, 2015 at 8:28 PM, eryksun wrote: > After disabling the check, my previous example should work fine: Except it doesn't accept paths relative to a UNC working directory: (test) \\127.0.0.1\C$>cd Temp The system cannot find the path specified. And the cd command appears to ignore the registry setting: (test) \\127.0.0.1\C$>cd \\127.0.0.1\C$\Temp '\\127.0.0.1\C$\Temp' CMD does not support UNC paths as current directories. Otherwise it works fine. ;-) From cs at zip.com.au Thu Apr 30 04:40:11 2015 From: cs at zip.com.au (Cameron Simpson) Date: Thu, 30 Apr 2015 12:40:11 +1000 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: References: Message-ID: <20150430024011.GA77453@cskk.homeip.net> On 29Apr2015 12:12, boB Stepp wrote: >> ... (3) install git if needed ... > >It seems Git is needed, but I am not allowed to install it on the >Solaris workstation. So is there a way around this? What do you mean by "install"? Bear in mind that while you may be forbidden from installing git in the main areas (/usr, /usr/local, whatever), you may be free to install it in your own home directory. It is just an executable... Cheers, Cameron Simpson From cs at zip.com.au Thu Apr 30 04:09:22 2015 From: cs at zip.com.au (Cameron Simpson) Date: Thu, 30 Apr 2015 12:09:22 +1000 Subject: [Tutor] Fwd: Function works one time then subsequently fails In-Reply-To: References: Message-ID: <20150430020922.GA18991@cskk.homeip.net> On 29Apr2015 08:34, Jim Mooney Py3.4.3winXP wrote: >On 28 April 2015 at 22:40, Cameron Simpson wrote: >> We can pick over your code as well if you like. Should we? > >Sure, but let me include the full working program after fixup. Although I >still have to write another program to feed it random problems to work it >out. It's a bit spacey, but I ran it through the pep8 program and it >suggested that. I think two spaces between such tiny functions is overkill, >though. > >""" >Takes the name of a binary math operation and two numbers from input, >repeatedly, and displays the results until done >""" > >def add(a, b): > return a + b > > >def subtract(a, b): > return b - a > > >def minus(a, b): > return a - b These could all do with docstrings. add() is pretty obvious, but the distinction between minus() and subtract() could do with elaboration. Also, I would be inclined to define minus() in terms of subtract(), not because it is faster but because it establishes an equivalence. >def multiply(a, b): > return a * b > > >def divide(a, b): > return a / b > > >operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract, >'subtracted': subtract, > '-': minus, 'minus': minus, 'multiply': multiply, '*': >multiply, 'multiplied': multiply, > 'times': multiply, 'divide': divide, '/': divide, 'divided': >divide} I'd make this much more vertical, like this: operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract, 'subtracted': subtract, Easier to maintain, easier to read, easier to modify, and if you use version control you will get much more meaningful diff output with changes, which aids code review (which more or less equates to readability and maintainability). >def test_number(astring): > """ > Input: A string that should represent a valid int or float. Output: > An int or float on success. None on failure. > """ > for make_type in (int, float): > try: > return make_type(astring) > except ValueError: > pass > return None If this is a test function, it should return True or False. Other have already remarked on this in other threads: the Pythonic way to do this is usually to attempt the conversion and let an exception get out: def numberify(astring): return float(astring) Consider the calling code. What are you going to do with it. I see you probe first, which makes some sense in lexical analysis: >def parse_string(math_string): > """Input: A math string with a verbal or mathematical operation > and two valid numbers to operate on. Extra numbers and operations > are ignored. Output: A tuple containing a function corresponding > to the operation and the two numbers. Returns None on failure. > """ > operation = None > tokens = math_string.split() > numbers = [] > for token in tokens: > if token in operations: > operation = operations[token] > elif test_number(token) != None: > numbers.append(test_number(token)) > if len(numbers) > 1: > break > if operation is None or len(numbers) < 2: > return None > else: > return operation, numbers[0], numbers[1] As a lexical exercise probing (test then act) is pretty common and normal. However, an alternative way to structure this is the "ask for forgiveness" approach: try: operation = operations[token] except KeyError: value = numberify(token) numbers.append(value) This will raise ValueError if it is neither an operation nor a number. The practice of raising an exception permits a mode of programming where both your code and the caller can broadly write the code as though values are generally valid, and avoids a lot error catching verbiage that obscures the core logic. In that vein, you would also modify the function to raise an exception (typically ValueError) for other invalid math_strings. The advantage here is that the caller can use your function like this: operation, *arguments = parse_string(math_string) and not perform any special testing for getting None back. Instead, the caller can plow on as though the math_string was valid as well. An exception can bubble up to a suitable catch point, such as the main loop which reads strings from the user. >instructions = '''Enter two numbers and one of the four basid math >operations, >either mathematical or verbal. i.e. 3 + 2, 12 divided by 14, 10 minus 4, >etc. >Enter done to quit. >''' >try: > user_input = input(instructions) > while True: > if user_input == 'done': > break While most programs will accept a special token to exit, you can also just rely on seeing end of file. Most systems have a way of indicating this from the keyboard, often ^Z in Windows and ^D on UNIX terminals. So since input() is documented as raising EOFError in this circumstance you could add that to your catch below: except EOFError: print("End of input from user.") Then, if parse_string() raises a ValueError in a Pythonic way you'd change: > result = parse_string(user_input) > if result == None: > print("Not a valid math operation.") > else: > func, num1, num2 = result > print(func(num1, num2)) into: try: operation, *arguments = parse_string(user_input) except ValueError as e: print("Invalid math operation: %s" % (e,)) else: print(func(*arguments)) Notice that by returning the numeric parts into a list you can later implement operations with other numbers of arguments than 2. > user_input = input() I would try to say that just once by putting it at the top of the loop, changing this: user_input = input(instructions) while True: into: prompt = instructions while True: user_input = input(prompt) prompt = '' thus calling input() from only one place. This also makes it easy to re-issue the instructions if the user offers invalid input by adding: prompt = instructions to the "except" clause for a bad math string. Finally, I might move main code into a main() function, which I would put at the _top_ of the program: def main(): instructions = ...... prompt = instructions while True: user_input = input(prompt) .............. and at the bottom put this boilerplate: if __name__ == '__main__': main() This final boilerplate is common in modules. When a python file is invoked directly the "module" name is "__main__". When the same python file is imported as a module, __name__ is the module name. This allows you to use the module as a main program in one circumstance and as a set of library functions when imported. The main program might be some primary function with code like yours or alternatively run various unit tests on the module functions if there is no natural "main program" to give the module. Often I have both a legitimate main program and also unit tests. In that circumstance I usually give the "main program" a "test" mode, which will run the unit tests. Cheers, Cameron Simpson From robertvstepp at gmail.com Thu Apr 30 05:10:02 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 22:10:02 -0500 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: <20150430024011.GA77453@cskk.homeip.net> References: <20150430024011.GA77453@cskk.homeip.net> Message-ID: On Wed, Apr 29, 2015 at 9:40 PM, Cameron Simpson wrote: > On 29Apr2015 12:12, boB Stepp wrote: >>> >>> ... (3) install git if needed ... >> >> >> It seems Git is needed, but I am not allowed to install it on the >> Solaris workstation. So is there a way around this? > > > What do you mean by "install"? Bear in mind that while you may be forbidden > from installing git in the main areas (/usr, /usr/local, whatever), you may > be free to install it in your own home directory. It is just an > executable... On the smart enterprise where we (now) do our clinical planning they are very strict: no installing any external software; no accessing the Internet; no email; etc. Not all centers adhere to this level of strictness, but ours does. To be honest, I am surprised they allow me to do the programming I do, but so far it has been all pluses and no minuses, and for those dosimetrists who choose to use the tools I have developed, they are more productive than they would be doing things by hand. Now the 810X Solaris workstation that was retired when we went to smart enterprise is *mine* and they really don't care anymore what I do with it. When it was being used for actual clinical planning, it had its Internet access disabled, etc. I have since restored it, so I could install software now, including Git. But I am reluctant to do anything that I am not allowed to replicate on smart enterprise. I am trying to keep it as close to identical to the actual clinical environment as I can. Perhaps this is misguided on my part? As always, I welcome your thoughts. It could be I am being unnecessarily cautious in regards to the 810X, but as has been pointed out there is much I do not know, so my motto is to first ensure I do no harm... -- boB From davea at davea.name Thu Apr 30 05:43:34 2015 From: davea at davea.name (Dave Angel) Date: Wed, 29 Apr 2015 23:43:34 -0400 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> Message-ID: <5541A4E6.3020209@davea.name> On 04/29/2015 02:37 PM, diliup gabadamudalige wrote: > I do not understand how Alan does not get the code that is in this thread. There are at least 3 ways of posting to "this thread": A) email B) newsgroup C) googlegroups and at least 5 ways of looking at "this thread" A) email B) email digest C) newsgroup D) googlegroups E) various archives To get messages from one region to another involves going through a gateway, and most of them damage some of the messages going through. To minimize the likelihood that what looks good on your screen will be missing or different on mine or on Alan's, follow a few rules: 1) avoid html 2) avoid attachments There are others, but those seem to be the biggies. Many other guidelines will help readability and consistency, like not top-posting, using proper quoting and attribution, giving enough information but not too much, specifying the whole environment in the FIRST message of a thread, etc. -- DaveA From robertvstepp at gmail.com Thu Apr 30 05:49:46 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 22:49:46 -0500 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: References: Message-ID: On Wed, Apr 29, 2015 at 4:42 PM, Mark Lawrence wrote: > This isn't a job for Bicycle Repair Man!!! Not even if we only use the latest, greatest, computer-aided bicycle repair technology??? > ... It smacks to me of dictionaries > and the operator module but I'm too bone idle to look it up myself, so try > here https://docs.python.org/3/library/operator.html > D'oh :) So little time, so much Python standard library! I *do* search and search and ... search before I ask, but my Google-fu is often weak, especially when I am searching for hints as to how to solve a problem where I am unsure of the correct technical terminology to use in the search. OTH, I have sometimes spent hours searching, both online and in what books I have, and thus spared y'all many, ... , many other questions that I might have otherwise asked! One problem I have with searching the Python documentation is this: https://docs.python.org/release/2.4.4/lib/lib.html I never would have guessed beforehand that I would be needing to look under: "3. Python Runtime Services! I spend most of my time on this page as this is my most limiting version of Python that I must deal with. This page is *not* well-formatted and it all runs together. Even when I *know* something is there, I find myself having to Ctrl-F and entering the term I am looking for. And when I am not sure what I am looking for, I don't usually come up with the correct term. The later Python docs are much easier on the eyes, I do say! Anyway, Mark, thanks for the link! This looks quite straightforward and I will be able to side-step the evils of eval() once again. -- boB From robertvstepp at gmail.com Thu Apr 30 05:57:26 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 22:57:26 -0500 Subject: [Tutor] Is there a way to store and later use comparison operators (<, <=, =, >=, >) ? In-Reply-To: References: Message-ID: On Wed, Apr 29, 2015 at 5:49 PM, Peter Otten <__peter__ at web.de> wrote: > boB Stepp wrote: >> So I have stumbled (With your gracious help!) into a legitimate use of >> eval()? > > No. To expand on Marks hint here's how to do it without evil eval(). > > import operator > > comps = { > "=": operator.eq, > "<": operator.lt, > ">": operator.gt, > # ... > } > > def choose_compare(operator, value0, value1, pass_color, fail_color): > op = comps[operator] > if op(value0, value1): > return pass_color, True > else: > return fail_color, False > > print(choose_compare("=", 1, 1, "red", "blue")) > print(choose_compare("<", 1, 2, "red", "blue")) > print(choose_compare("<", 2, 1, "red", "blue")) > > Rule of thumb: when you think you need eval() you're wrong. Thanks, Peter! The lure of eval() once more avoided... -- boB From cs at zip.com.au Thu Apr 30 05:39:25 2015 From: cs at zip.com.au (Cameron Simpson) Date: Thu, 30 Apr 2015 13:39:25 +1000 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: References: Message-ID: <20150430033925.GA10288@cskk.homeip.net> On 29Apr2015 22:10, boB Stepp wrote: >On Wed, Apr 29, 2015 at 9:40 PM, Cameron Simpson wrote: >> On 29Apr2015 12:12, boB Stepp wrote: >>>> ... (3) install git if needed ... >>> >>> It seems Git is needed, but I am not allowed to install it on the >>> Solaris workstation. So is there a way around this? >> >> What do you mean by "install"? Bear in mind that while you may be forbidden >> from installing git in the main areas (/usr, /usr/local, whatever), you may >> be free to install it in your own home directory. It is just an >> executable... > >On the smart enterprise where we (now) do our clinical planning they >are very strict: no installing any external software; no accessing the >Internet; no email; etc. Not all centers adhere to this level of >strictness, but ours does. [...] But I am reluctant to do >anything that I am not allowed to replicate on smart enterprise. I am >trying to keep it as close to identical to the actual clinical >environment as I can. And fair enough too. I frequently wish our developers' dev environments more rigorously modelled the target environment. >Perhaps this is misguided on my part? Not necessarily. But I would be inclined to distinguish your working tools from the target environment. For example, I commend you making your dev environment as close to identical to the actual clinical environment as you can. But I wouldn't deprive yourself of tools that enhance your code management practices without affecting that environment. For example, there is much to be said for tracking your changes with a tool like git or hg. It encourages your to annotate your changes, and lets you review history to see when and why some change occurred, especially if a new bug has arisen. Distributed version control systems like git and hg also make it easier to work on distinct changes to the same code as separate work processes; of course the price for such a workflow is that you need to merge the two things later and ensure that they do not interact badly. If you're serious about keeping the two environments very similar, you could always do your _coding_ on a third platform (a laptop or whatever) using your desired tools and _deploy_ the code to the dev (and later, prod) environments from there, keeping the dev environment pristine. By "deploy", that can be as simple as copying the code to the target. Just thoughts; of course you must choose practices that suit your needs and plans. Cheers, Cameron Simpson Nothing is impossible for the man who doesn't have to do it. From davea at davea.name Thu Apr 30 06:14:57 2015 From: davea at davea.name (Dave Angel) Date: Thu, 30 Apr 2015 00:14:57 -0400 Subject: [Tutor] raise exception works as planned in program but not when imported into testing module In-Reply-To: References: Message-ID: <5541AC41.9010702@davea.name> On 04/29/2015 09:05 PM, Jim Mooney Py3.4.3winXP wrote: > I raised an exception in the parse_string function in my math parser > program, function_tosser.py, and caught it in the calling routine, and that > worked fine. But when I imported function_tosser.py into a test program, > tester.py, it threw the exception in the parse_string function instead of > handling it in the try block in the calling routine. Why did it work in one > and not the other? The testing program works fine if I return None as I did > before, instead of raising the exception. It'd be nice if you were explicit about which code you're describing. I can make guesses, but your above paragraph leaves a lot of confusion. I'm guessing you're talking about the line in parse_string(): raise ValueError And I assume you're talking about it being referenced in the other file by the line: print(ft.parse_string(monkey_wrench), '\n') But why are you surprised? There's no try/except protecting the latter line, so the exception will be uncaught, and you'll see it reported in parse_string(). > in the try block in the calling routine. What routine is that? The line I quoted above is in top-level code, not in a routine. And it doesn't have a try/except there. > > # function_tosser.py > """ > Takes the name of a binary math operation and two numbers from input, > repeatedly, and displays the results until done > """ > > > def add(a, b): > return a + b > > > def subtract(a, b): > return b - a > > def minus(a, b): > return a - b > > > def multiply(a, b): > return a * b > > > def divide(a, b): > return a / b > > > operations = {'add': add, '+': add, 'plus': add, 'subtract': subtract, > 'subtracted': subtract, > '-': minus, 'minus': minus, 'multiply': multiply, '*': > multiply, 'multiplied': multiply, > 'times': multiply, 'divide': divide, '/': divide, 'divided': > divide} > > def test_number(astring): > """ > Input: A string that should represent a valid int or float. Output: > An int or float on success. None on failure. > """ > for make_type in (int, float): > try: > return make_type(astring) > except ValueError: # Previously returned None, which worked. This > works fine here but when imported into the test program > pass # it doesn't wait for the try block in the > calling routine. > return None > > > def parse_string(math_string): > """Input: A math string with a verbal or mathematical operation > and two valid numbers to operate on. Extra numbers and operations > are ignored. Output: A tuple containing a function corresponding > to the operation and the two numbers. Returns None on failure. > """ > operation = None > tokens = math_string.split() > numbers = [] > for token in tokens: > if token in operations: > operation = operations[token] > elif test_number(token) != None: > numbers.append(test_number(token)) > if len(numbers) > 1: > break > if operation is None or len(numbers) < 2: > raise ValueError > else: > return operation, numbers[0], numbers[1] > > if __name__ == "__main__": > instructions = '''Enter two numbers and one of the four basid math > operations, > either mathematical or verbal. i.e. 3 + 2, 12 divided by 14, 10 minus > 4, etc. > Enter done to quit. > ''' > try: > user_input = input(instructions) > while True: > if user_input == 'done': > break > try: > result = parse_string(user_input) > except ValueError: > print("Not a valid math operation.") > else: > func, num1, num2 = result > print(func(num1, num2)) > user_input = input() > except KeyboardInterrupt: > print("Program terminated by user") > > # tester.py > > '''Test function_tosser.py mainlogic against random operators, operands, > and bad input''' > import random > import function_tosser as ft > valid_terms = list(ft.operations.keys()) > def eval_test(): > pass > > trash = ['1 +', 'blah', '3-4', 'gargle', 'Newt Gingrich', > ",,,,,", '{+=-33.44 minus12 3 times blarg 1445641654644555455'] > > for ctr in range(50): > term = ' ' + random.choice(valid_terms) + ' ' > num1 = str(random.randint(1,1000)) > num2 = str(random.randint(1,1000)) > if term == ' subtract ' or term == ' subtracted ': term = ' subtracted > from ' > if ctr % 10 == 0: # stress testing for a None failure > monkey_wrench = random.choice(trash) > print(ft.parse_string(monkey_wrench), '\n') > else: > func, num1, num2 = ft.parse_string(num1 + term + num2) > print(func, num1, term, num2) > print('result:',func(num1, num2), '\n') > > -- DaveA From robertvstepp at gmail.com Thu Apr 30 06:28:59 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 29 Apr 2015 23:28:59 -0500 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: <20150430033925.GA10288@cskk.homeip.net> References: <20150430033925.GA10288@cskk.homeip.net> Message-ID: On Wed, Apr 29, 2015 at 10:39 PM, Cameron Simpson wrote: > On 29Apr2015 22:10, boB Stepp wrote: >> On the smart enterprise where we (now) do our clinical planning they >> are very strict: no installing any external software; no accessing the >> Internet; no email; etc. Not all centers adhere to this level of >> strictness, but ours does. [...] But I am reluctant to do >> anything that I am not allowed to replicate on smart enterprise. I am >> trying to keep it as close to identical to the actual clinical >> environment as I can. > > > And fair enough too. I frequently wish our developers' dev environments more > rigorously modelled the target environment. > >> Perhaps this is misguided on my part? > > > Not necessarily. > > But I would be inclined to distinguish your working tools from the target > environment. > > For example, I commend you making your dev environment as close to identical > to the actual clinical environment as you can. But I wouldn't deprive > yourself of tools that enhance your code management practices without > affecting that environment. > > For example, there is much to be said for tracking your changes with a tool > like git or hg. It encourages your to annotate your changes, and lets you > review history to see when and why some change occurred, especially if a new > bug has arisen. Distributed version control systems like git and hg also > make it easier to work on distinct changes to the same code as separate work > processes; of course the price for such a workflow is that you need to merge > the two things later and ensure that they do not interact badly. Totally, totally convinced of the correctness of this. Actively working to implement this. See below. > If you're serious about keeping the two environments very similar, you could > always do your _coding_ on a third platform (a laptop or whatever) using > your desired tools and _deploy_ the code to the dev (and later, prod) > environments from there, keeping the dev environment pristine. By "deploy", > that can be as simple as copying the code to the target. That is what I have implemented as of today. I installed Git on my Windows PC where I have been doing my actual coding anyway, created the needed repositories, including an extra one on our intranet in case my PC dies, etc. The current project is now in version control. After doing some editing and saving, I use the Git bash shell that came with Git and scp the file(s) to the dev environment, do my testing (Still manual; working on getting automated, but this will have more of a learning curve for me than using Git.), etc. When I get a meaningful chunk of something done, I add and commit in Git on the Windows PC. Less often I push to the intranet repo. Your comments suggest that I am on a reasonable track. The main danger as I see it is that if I am not careful, then the code on the dev environment could diverge from the state of code on my Windows PC, i.e., I forgot to do the scp part. But when I am actively working on a section of code I always insert a few print statements (Py 2.4!) to verify I am getting what I should when I test it out--even if I don't have an actual problem yet. And so far this has immediately revealed those few instances so far when I forgot to save to the dev machine (Usually when someone has interrupted my workflow, a near constant occurrence at work.). -- boB From davea at davea.name Thu Apr 30 06:38:21 2015 From: davea at davea.name (Dave Angel) Date: Thu, 30 Apr 2015 00:38:21 -0400 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: References: <20150430033925.GA10288@cskk.homeip.net> Message-ID: <5541B1BD.6030600@davea.name> On 04/30/2015 12:28 AM, boB Stepp wrote: > The main danger as I see it is that if I am not careful, then the code > on the dev environment could diverge from the state of code on my > Windows PC, i.e., I forgot to do the scp part. But when I am actively > working on a section of code I always insert a few print statements > (Py 2.4!) to verify I am getting what I should when I test it > out--even if I don't have an actual problem yet. And so far this has > immediately revealed those few instances so far when I forgot to save > to the dev machine (Usually when someone has interrupted my workflow, > a near constant occurrence at work.). > > Add an automatic file copy to the save-key definition in your editor. Then whenever you save the file locally, you'll also be copying it to the master location. If that's too hard, or your editor can't support it, write a bash script that does an rsynch every 10 minutes. rsynch does what scp does, but it works on whole directories, copying only those files that changed. And you can fine tune what "changed" means. There are other, less resource intense approaches, but if one of these works, it'll be pretty painless to set up. -- DaveA From ben+python at benfinney.id.au Thu Apr 30 07:15:26 2015 From: ben+python at benfinney.id.au (Ben Finney) Date: Thu, 30 Apr 2015 15:15:26 +1000 Subject: [Tutor] Ancient Python versions (was: Is there a way to store and later use comparison operators (<, <=, =, >=, >) ?) References: Message-ID: <85lhhai4cx.fsf_-_@benfinney.id.au> boB Stepp writes: > One problem I have with searching the Python documentation is this: > https://docs.python.org/release/2.4.4/lib/lib.html If you actually need to read the documentation specifically for a Python version that has not been supported since 2008, then I agree that is a problem. The documentation has improved since then. If you want newer-looking documentation, maybe you should not expect it from a Python released nearlt a decade ago? -- \ ?Not to be absolutely certain is, I think, one of the essential | `\ things in rationality.? ?Bertrand Russell | _o__) | Ben Finney From cybervigilante at gmail.com Thu Apr 30 08:04:16 2015 From: cybervigilante at gmail.com (Jim Mooney Py3.4.3winXP) Date: Wed, 29 Apr 2015 23:04:16 -0700 Subject: [Tutor] raise exception works as planned in program but not when imported into testing module In-Reply-To: <5541AC41.9010702@davea.name> References: <5541AC41.9010702@davea.name> Message-ID: On 29 April 2015 at 21:14, Dave Angel wrote: > But why are you surprised? There's no try/except protecting the latter > line, so the exception will be uncaught, and you'll see it reported in > parse_string(). > I think I meant something like this. An exception in a function is caught by the caller. I imported the program that did this into the test program, expecting the exception to still be caught when the parse_string was called, by the try except else block in the mainroutine of the imported program.. def excepter(): raise ValueError try: excepter() except ValueError: print("Exception caught after function call") REPL >>> Exception caught after function call >>> -- Jim "What a rotten, failed experiment. I'll start over. Maybe dogs instead of monkeys this time." --God From cybervigilante at gmail.com Thu Apr 30 08:16:12 2015 From: cybervigilante at gmail.com (Jim Mooney Py3.4.3winXP) Date: Wed, 29 Apr 2015 23:16:12 -0700 Subject: [Tutor] Fwd: Function works one time then subsequently fails In-Reply-To: <20150430020922.GA18991@cskk.homeip.net> References: <20150430020922.GA18991@cskk.homeip.net> Message-ID: Sure, but let me include the full working program after fixup.... On 29 April 2015 at 19:09, Cameron Simpson wrote: > > These could all do with docstrings. add() is pretty obvious, but the > distinction between minus() and subtract() could do with elaboration. etc, etc. Thanks. Very comprehensive. I'll print it out and ponder it ;') -- Jim "What a rotten, failed experiment. I'll start over. Maybe dogs instead of monkeys this time." --God From cybervigilante at gmail.com Thu Apr 30 09:08:04 2015 From: cybervigilante at gmail.com (Jim Mooney Py3.4.3winXP) Date: Thu, 30 Apr 2015 00:08:04 -0700 Subject: [Tutor] raise exception works as planned in program but not when imported into testing module In-Reply-To: References: <5541AC41.9010702@davea.name> Message-ID: Oops, my mistake. Ignore dumb remark below. I was thinking of the try - except in the main loop, but since I only tested the parse function, I never used that. I need to look a bit harder and find this stuff Before I post ;') Jim On 29 April 2015 at 23:04, Jim Mooney Py3.4.3winXP wrote: > > I think I meant something like this. An exception in a function is caught > by the caller. I imported the program that did this into the test program, > expecting the exception to still be caught when the parse_string was > called, by the try except else block in the mainroutine of the imported > program.. > > def excepter(): > raise ValueError > > try: > excepter() > except ValueError: > print("Exception caught after function call") > > REPL > >>> > Exception caught after function call > -- Jim "What a rotten, failed experiment. I'll start over. Maybe dogs instead of monkeys this time." --God From braveart08 at yahoo.com.au Thu Apr 30 05:58:25 2015 From: braveart08 at yahoo.com.au (Jag Sherrington) Date: Thu, 30 Apr 2015 03:58:25 +0000 (UTC) Subject: [Tutor] Newbie problems Message-ID: <465451395.1213571.1430366305635.JavaMail.yahoo@mail.yahoo.com> Can anyone please tell me what I am doing wrong?As this code I have for the Roulette Wheel colours exercise, won't work.?number = int(input('Enter a number between 0 and 36: '))green_number = (0)?red_number = (1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36)?black_number = (2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 34, 29, 31, 33, 35) if number == green_number:? ? print('Number is Green')? ??elif number == red_number:? ? print('Number is Red')? ??elif number == black_number:? ? ? ? print('Number is Black') Thank you for any help, Jag From diliupg at gmail.com Thu Apr 30 08:57:57 2015 From: diliupg at gmail.com (diliup gabadamudalige) Date: Thu, 30 Apr 2015 12:27:57 +0530 Subject: [Tutor] Fwd: circular movement in pygame In-Reply-To: <5541A4E6.3020209@davea.name> References: <554014CA.90601@davea.name> <554095BF.2000208@btinternet.com> <5541A4E6.3020209@davea.name> Message-ID: Thanks all for the very informative responses especially to Alan for being descriptive. I am now going to make my movement linear and move away from my current circular one. I hope a little bit of fun and "Thank you" emails fall into the order of the day.. :) On Thu, Apr 30, 2015 at 9:13 AM, Dave Angel wrote: > On 04/29/2015 02:37 PM, diliup gabadamudalige wrote: > >> I do not understand how Alan does not get the code that is in this thread. >> > > There are at least 3 ways of posting to "this thread": > A) email > B) newsgroup > C) googlegroups > > and at least 5 ways of looking at "this thread" > A) email > B) email digest > C) newsgroup > D) googlegroups > E) various archives > > To get messages from one region to another involves going through a > gateway, and most of them damage some of the messages going through. To > minimize the likelihood that what looks good on your screen will be missing > or different on mine or on Alan's, follow a few rules: > > 1) avoid html > 2) avoid attachments > > There are others, but those seem to be the biggies. > > Many other guidelines will help readability and consistency, like not > top-posting, using proper quoting and attribution, giving enough > information but not too much, specifying the whole environment in the FIRST > message of a thread, etc. > > -- > DaveA > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor > -- Diliup Gabadamudalige http://www.diliupg.com http://soft.diliupg.com/ ********************************************************************************************** This e-mail is confidential. It may also be legally privileged. If you are not the intended recipient or have received it in error, please delete it and all copies from your system and notify the sender immediately by return e-mail. Any unauthorized reading, reproducing, printing or further dissemination of this e-mail or its contents is strictly prohibited and may be unlawful. Internet communications cannot be guaranteed to be timely, secure, error or virus-free. The sender does not accept liability for any errors or omissions. ********************************************************************************************** From lac at openend.se Thu Apr 30 08:02:33 2015 From: lac at openend.se (Laura Creighton) Date: Thu, 30 Apr 2015 08:02:33 +0200 Subject: [Tutor] Python 2.4 (was comparison operators) In-Reply-To: Message from boB Stepp of "Wed, 29 Apr 2015 22:49:46 -0500." References: Message-ID: <201504300602.t3U62XvL010296@fido.openend.se> Python 2.4 is really old, right now. OpenCSW has 2.6.9 http://www.opencsw.org/package/python/ Any chance you could use that? Laura From lac at openend.se Thu Apr 30 08:12:55 2015 From: lac at openend.se (Laura Creighton) Date: Thu, 30 Apr 2015 08:12:55 +0200 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: Message from boB Stepp of "Wed, 29 Apr 2015 23:28:59 -0500." References: <20150430033925.GA10288@cskk.homeip.net> Message-ID: <201504300612.t3U6Ct3Y010718@fido.openend.se> In a message of Wed, 29 Apr 2015 23:28:59 -0500, boB Stepp writes: >The main danger as I see it is that if I am not careful, then the code >on the dev environment could diverge from the state of code on my >Windows PC, i.e., I forgot to do the scp part. But when I am actively >working on a section of code I always insert a few print statements >(Py 2.4!) to verify I am getting what I should when I test it >out--even if I don't have an actual problem yet. And so far this has >immediately revealed those few instances so far when I forgot to save >to the dev machine (Usually when someone has interrupted my workflow, >a near constant occurrence at work.). If you can get git running on your solaris development machine, you can get out of the 'manually copying files' business. You can just ask git for an up to date version of all your code, all your tests, all your documentation -- all the files. :) From smarugg at gmail.com Thu Apr 30 04:59:48 2015 From: smarugg at gmail.com (Spencer For Friends) Date: Wed, 29 Apr 2015 22:59:48 -0400 Subject: [Tutor] if/then statement and sql count rows Message-ID: Hi All, I'm attempting to perform an if then statement based on the results of a sql count rows query. The query is returning the proper values however the if/then statement seems to be ignoring the returned value of the sql statement. Here is my code. import sqlite3 # Define SQL statement to select all Data from Column Name sql = "SELECT Count(*) FROM arbtable WHERE Name = ?" book_name = 'Winged Coat' class PriceCheck(object): def __init__(self, db): self.conn = sqlite3.connect(db) self.c = self.conn.cursor() def query(self, arg, cardname): self.c.execute(arg, cardname) return self.c def __del__(self): self.conn.close() def display(): #Connect To DB and Get Price of Matched book. getbookprice = PriceCheck("arbbase.sqlite") for row in getbookprice.query(sql, ([book_name])): if row == 0: print 'no row was found' else: print 'Yep its there!' print row display() The program here is that my result, as evidenced by "print row" at the bottom of the code is 0. Since it is zero according to my if statement it should print 'no row was found', but instead it prints the else statement value of 'yes its there!' I've researched extensively and think that possibly the fetchone statement is what I need, but I can't seem to figure out how to properly apply this to my code to test it. Any help would be highly appreciated. Thank you kindly Sour Jack From alan.gauld at btinternet.com Thu Apr 30 10:15:07 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 30 Apr 2015 09:15:07 +0100 Subject: [Tutor] subprocess.Popen(..., cwd) and UNC paths In-Reply-To: References: <1430326451.93582.BPMail_high_carrier@web163803.mail.gq1.yahoo.com> Message-ID: <5541E48B.6070807@btinternet.com> On 30/04/15 01:48, eryksun wrote: > > Actually cmd.exe is fine with UNC paths. > cmd.exe cannot use a UNC path as the current directory. Oops, my mistake. I got my POSIX and UNC mixed up. I was thinking about forward slashes etc not network names. Apologies for not reading the message properly. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From davea at davea.name Thu Apr 30 10:27:30 2015 From: davea at davea.name (Dave Angel) Date: Thu, 30 Apr 2015 04:27:30 -0400 Subject: [Tutor] Newbie problems In-Reply-To: <465451395.1213571.1430366305635.JavaMail.yahoo@mail.yahoo.com> References: <465451395.1213571.1430366305635.JavaMail.yahoo@mail.yahoo.com> Message-ID: <5541E772.4020906@davea.name> On 04/29/2015 11:58 PM, Jag Sherrington wrote: > Can anyone please tell me what I am doing wrong?As this code I have for the Roulette Wheel colours exercise, won't work. number = int(input('Enter a number between 0 and 36: '))green_number = (0) red_number = (1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36) black_number = (2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 34, 29, 31, 33, 35) > if number == green_number: print('Number is Green') elif number == red_number: print('Number is Red') elif number == black_number: print('Number is Black') > Thank you for any help, Jag > Please post your code the way you're going to run it, like one statement per line, indented as required, etc. Your problem is you're comparing an int (number) to a list (green_number or red_number or black_number). They'll never be equal so it won't print anything. presumably you don't want to know if the number is equal to the list, but whether it's in the list. The "in" operator will tell you that. Something like: if number in green_numbers: (I changed it to plural, so it'd be more obvious that it's not a single value, but a list of them. Little things like that can make errors much easier to spot.) -- DaveA From alan.gauld at btinternet.com Thu Apr 30 10:28:07 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 30 Apr 2015 09:28:07 +0100 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: References: <20150430033925.GA10288@cskk.homeip.net> Message-ID: On 30/04/15 05:28, boB Stepp wrote: > That is what I have implemented as of today. I installed Git on my > Windows PC where I have been doing my actual coding This is off topic but due to your peculiar restrictions might be useful so I thought I'd bring it up. Do you have Cygwin installed on your PC? Its a Unix-like user environment that runs on Windows including Python and the other tools (including X windows). It makes writing and testing code for a Unix box on a Windows box very much easier. If you haven't investigated it before I strongly recommend it. -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Thu Apr 30 10:40:14 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 30 Apr 2015 09:40:14 +0100 Subject: [Tutor] Newbie problems In-Reply-To: <465451395.1213571.1430366305635.JavaMail.yahoo@mail.yahoo.com> References: <465451395.1213571.1430366305635.JavaMail.yahoo@mail.yahoo.com> Message-ID: On 30/04/15 04:58, Jag Sherrington wrote: > Can anyone please tell me what I am doing wrong?As this code I have for the Roulette Wheel colours exercise, won't work. number = int(input('Enter a number between 0 and 36: '))green_number = (0) red_number = (1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36) black_number = (2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 34, 29, 31, 33, 35) > if number == green_number: print('Number is Green') elif number == red_number: print('Number is Red') elif number == black_number: print('Number is Black') > Thank you for any help, Jag The first problem is that you are posting in HTML which is losing all the code formatting, making it hard to read. Also you don't actually tell us what doesn't work. If you get an error message post it. If you get different results to what you expect tell us what you expect and what you got. For now I'll take a guess below... number = int(input('Enter a number between 0 and 36: ')) green_number = (0) red_number = (1, 3, 5, 7, 9, 12, 14, 16, 18, 19, 21, 23, 25, 27, 30, 32, 34, 36) black_number = (2, 4, 6, 8, 10, 11, 13, 15, 17, 20, 22, 24, 26, 28, 34, 29, 31, 33, 35) if number == green_number: print('Number is Green') elif number == red_number: print('Number is Red') elif number == black_number: print('Number is Black') Note that you are testing the number for equality, which means it must be exactly the same value. But your red_number and black_number are both tuples of several numbers so a single number will never equal a sequence of numbers. You should use the 'in' test instead of equals. Like if number in red_number: -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From alan.gauld at btinternet.com Thu Apr 30 10:46:49 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 30 Apr 2015 09:46:49 +0100 Subject: [Tutor] if/then statement and sql count rows In-Reply-To: References: Message-ID: On 30/04/15 03:59, Spencer For Friends wrote: > class PriceCheck(object): > def __init__(self, db): > self.conn = sqlite3.connect(db) > self.c = self.conn.cursor() > > > def query(self, arg, cardname): > self.c.execute(arg, cardname) > return self.c You are returning the cursor object here. That's probably not what the user of your code wants, it would be better to return the actual result. You can get that using fetchone() or fetchall() Since count() can only return one value fetchone() would be best here. return self.c.fetchone() > def __del__(self): > self.conn.close() > > def display(): > #Connect To DB and Get Price of Matched book. > getbookprice = PriceCheck("arbbase.sqlite") > for row in getbookprice.query(sql, ([book_name])): Insert a debug statement here: print type(row), ':', row And see if what you get is what you expect. > if row == 0: > print 'no row was found' > else: > print 'Yep its there!' > print row -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From robertvstepp at gmail.com Thu Apr 30 16:34:44 2015 From: robertvstepp at gmail.com (boB Stepp) Date: Thu, 30 Apr 2015 09:34:44 -0500 Subject: [Tutor] How to use Git from Windows PC for files on Solaris machine where Git cannot be installed? In-Reply-To: <5541B1BD.6030600@davea.name> References: <20150430033925.GA10288@cskk.homeip.net> <5541B1BD.6030600@davea.name> Message-ID: On Wed, Apr 29, 2015 at 11:38 PM, Dave Angel wrote: > On 04/30/2015 12:28 AM, boB Stepp wrote: >> >> The main danger as I see it is that if I am not careful, then the code >> on the dev environment could diverge from the state of code on my >> Windows PC, i.e., I forgot to do the scp part. But when I am actively >> working on a section of code I always insert a few print statements >> (Py 2.4!) to verify I am getting what I should when I test it >> out--even if I don't have an actual problem yet. And so far this has >> immediately revealed those few instances so far when I forgot to save >> to the dev machine (Usually when someone has interrupted my workflow, >> a near constant occurrence at work.). >> >> > > Add an automatic file copy to the save-key definition in your editor. Then > whenever you save the file locally, you'll also be copying it to the master > location. Many, many thanks, Dave! This was easily done in and will match my local and remote file saves exactly as they need to be. It did not even occur to me that this feature existed. Heavy, sigh! I have so many blind spots... -- boB From roel at roelschroeven.net Thu Apr 30 21:22:58 2015 From: roel at roelschroeven.net (Roel Schroeven) Date: Thu, 30 Apr 2015 21:22:58 +0200 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: Alan Gauld schreef op 2015-04-30 00:51: > ... > Trying to visually scan for _ or even __ is hard. Also different > fonts make _ and __ hard to distinguish. > ... > But they will be. Almost for certain. It's human nature and the nature > of code maintenance. If it's there somebody will find a use for it. The > fact that 5 or 10 years earlier the author didn't intend for it to be > used is immaterial. Summarizing a bit, I think you make two main points (please correct me if I'm wrong): [1] Visually scanning for _ or __ is hard, and _ are __ hard to distinguish from each other. Personally, I find it easy to scan for them, but I think I can see whee you're coming from. Python tends to prefer words and tends to dislike symbols compared to e.g. C, C++, and certainly Perl. One could argue that using _ or __ goes against that, though to me it's not a problem. We're still very far from Perl's line noise. It's true that _ and __ can be difficult to be distinguished from each other, but that's also not a problem to me, since I don't care about their values. [2] Inevitably, sooner or later someone somewhere will start using _ or __ despite the fact that by convention they should not be used. I have to admit that I have no experience programming in larger teams, and was blissfully unaware of the problems you describe. I think I can see how it might be better to avoid __ rather than try to enforce good coding discipline. I still feel __ to be valuable, but I can see now where your dislike for it is coming from. Thank you for your insights! Best regards, Roel -- The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom. -- Isaac Asimov Roel Schroeven From davea at davea.name Thu Apr 30 21:33:49 2015 From: davea at davea.name (Dave Angel) Date: Thu, 30 Apr 2015 15:33:49 -0400 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: <5542839D.10700@davea.name> On 04/30/2015 03:22 PM, Roel Schroeven wrote: > Alan Gauld schreef op 2015-04-30 00:51: > > > ... > >> Trying to visually scan for _ or even __ is hard. Also different >> fonts make _ and __ hard to distinguish. > > > ... > >> But they will be. Almost for certain. It's human nature and the nature >> of code maintenance. If it's there somebody will find a use for it. >> The fact that 5 or 10 years earlier the author didn't intend for it to >> be used is immaterial. > > Summarizing a bit, I think you make two main points (please correct me > if I'm wrong): > > [1] Visually scanning for _ or __ is hard, and _ are __ hard to > distinguish from each other. > > Personally, I find it easy to scan for them, but I think I can see whee > you're coming from. Python tends to prefer words and tends to dislike > symbols compared to e.g. C, C++, and certainly Perl. One could argue > that using _ or __ goes against that, though to me it's not a problem. > We're still very far from Perl's line noise. > It's true that _ and __ can be difficult to be distinguished from each > other, but that's also not a problem to me, since I don't care about > their values. > > > [2] Inevitably, sooner or later someone somewhere will start using _ or > __ despite the fact that by convention they should not be used. > > I have to admit that I have no experience programming in larger teams, > and was blissfully unaware of the problems you describe. I think I can > see how it might be better to avoid __ rather than try to enforce good > coding discipline. > > > I still feel __ to be valuable, but I can see now where your dislike for > it is coming from. Thank you for your insights! > Well, are you aware that _ has a meaning in the debugger? It holds the last value of an expression that wasn't assigned to a variable. or something like that. So even if you don't have any coworkers, you might trip on someone else's assumptions. To see what I'm talking about: >>> 3*4 12 >>> print(_) 12 > Best regards, > Roel > -- DaveA From roel at roelschroeven.net Thu Apr 30 21:52:59 2015 From: roel at roelschroeven.net (Roel Schroeven) Date: Thu, 30 Apr 2015 21:52:59 +0200 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: <5542839D.10700@davea.name> References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> <5542839D.10700@davea.name> Message-ID: Dave Angel schreef op 2015-04-30 21:33: > Well, are you aware that _ has a meaning in the debugger? It holds the > last value of an expression that wasn't assigned to a variable. or > something like that. Yes, I know the meaning of _ in Python's interactive mode. It's something I sometimes use for convenience, but never really rely on. To me interactive mode is for trying out simple things, not for serious stuff. Anyway, as explained in this style guide it's better to use __ anyway instead of _: http://docs.python-guide.org/en/latest/writing/style/#create-an-ignored-variable -- The saddest aspect of life right now is that science gathers knowledge faster than society gathers wisdom. -- Isaac Asimov Roel Schroeven From alan.gauld at btinternet.com Thu Apr 30 23:12:37 2015 From: alan.gauld at btinternet.com (Alan Gauld) Date: Thu, 30 Apr 2015 22:12:37 +0100 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: On 30/04/15 20:22, Roel Schroeven wrote: > Alan Gauld schreef op 2015-04-30 00:51: > Summarizing a bit, I think you make two main points (please correct me > if I'm wrong): Your quite correct. I'm probably a bit paranoid but as I said I spent a significant bit of my production-programming career (about 40%) on maintenance projects and I've seen the horrors that come from uninitialised variables, misused names etc etc. And any kind of meaningless symbiol (even if the meaning is not needed at the time). And in a maintenance team where you are targetted to fix, say, 4 bugs per day, a "horror" is anything that adds more than say 15-20 minutes to the process! > [1] Visually scanning for _ or __ is hard, and _ are __ hard to > distinguish from each other. > > Personally, I find it easy to scan for them, but I think I can see whee > you're coming from. Python tends to prefer words and tends to dislike > symbols Yes but worse in this cae is tat Python uses __ for special purposes so if there is a __ near to a variable name the reader is likely to assume its just a pre-pended dunder marker rather than a separate name. It also makes searching for dunders harder since there are likely to be quite a few in the code already. (yes you can create a regex search but making it reliable is quite tricky.) > [2] Inevitably, sooner or later someone somewhere will start using _ or > __ despite the fact that by convention they should not be used. > > I have to admit that I have no experience programming in larger teams, > and was blissfully unaware of the problems you describe. Again my experience is not typical of the tutor forum, but some tutor readers may go on to bigger things and bad habits once learned become permanent... My smallest project team was 7 programmers producing 80,000 lines of code. Next smallest 18, producing 250,000. Most of my projects have had over 100 programmers and several million LOC (usually C++ or COBOL) One project had over 1000 programmers and produced 60 million LOC using 7(?) different programming languages. (I ran one of the maintenance teams of ~10 coders all fresh from uni') Like I say I get paranoid about some things :-) -- Alan G Author of the Learn to Program web site http://www.alan-g.me.uk/ http://www.amazon.com/author/alan_gauld Follow my photo-blog on Flickr at: http://www.flickr.com/photos/alangauldphotos From lac at openend.se Thu Apr 30 23:59:09 2015 From: lac at openend.se (Laura Creighton) Date: Thu, 30 Apr 2015 23:59:09 +0200 Subject: [Tutor] Good Taste Question: Using SQLite3 in Python In-Reply-To: Message from Roel Schroeven of "Thu, 30 Apr 2015 21:22:58 +0200." References: <55404A9D.5010103@gmail.com> <554100DD.3080000@gmail.com> Message-ID: <201504302159.t3ULxAiw010580@fido.openend.se> The fact that _ and __ are intended as throw away values is only clear to people who have read a particular doc about coding styles. If you haven't read the doc, you don't know what is going on. I name my throw away variables junk, and if there are lots of them, for instance when I am reading from a list of tuples, but only care about the fourth item in each tuple, its 'junk1, junk2, junk3 ...' So far I have yet to meet somebody who wasn't immediately aware that I did not care about those values. Laura