From guest0x013 at gmail.com Mon Jan 1 16:38:39 2018 From: guest0x013 at gmail.com (Pi) Date: Mon, 1 Jan 2018 22:38:39 +0100 Subject: [Tutor] checking connection to internet until success Message-ID: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com> Hi Tutor, with this code i am getting actual date from internet. I need correct date, because i am not sure this set on computer is right. import requests, time try: ??? OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10] ??? OffLineDate = time.strftime("%Y-%m-%d") ??? if OnLineDate == OffLineDate: ? ? ? ? do_something ? ? else: ? ? ? ? do_something_else except requests.ConnectionError: ??? print("Can not connect.") But this code is run once. And i am stuck. Tries with while loop doesnt took any advance. I was thinking about something like after method used in tkinter, but still i cant figure out how do this. Can You guide me, how check connection to internet to check for every lets say 30 seconds until success? Best regards From __peter__ at web.de Tue Jan 2 11:20:38 2018 From: __peter__ at web.de (Peter Otten) Date: Tue, 02 Jan 2018 17:20:38 +0100 Subject: [Tutor] checking connection to internet until success References: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com> Message-ID: Pi wrote: > Hi Tutor, > > with this code i am getting actual date from internet. I need correct > date, because i am not sure this set on computer is right. > > import requests, time > > try: > OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10] > OffLineDate = time.strftime("%Y-%m-%d") > > if OnLineDate == OffLineDate: > > do_something > > else: > > do_something_else > > > except requests.ConnectionError: > print("Can not connect.") > > But this code is run once. And i am stuck. Tries with while loop doesnt > took any advance. I was thinking about something like after method used > in tkinter, but still i cant figure out how do this. Can You guide me, > how check connection to internet to check for every lets say 30 seconds > until success? You are on the right track with the while-loop. You can use the else clause of the try...except construct to break out of the loop once you have successfully read the date: # untested import requests, time while True: # run forever try: OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10] except requests.ConnectionError: print("Can not connect.") else: # no exception OffLineDate = time.strftime("%Y-%m-%d") if OnLineDate == OffLineDate: do_something else: do_something_else break # out of the while-True loop time.sleep(30) # try again after 30 seconds If you want to give up after a few tries replace the while loop with for attempt in range(max_attempts): ... # same as above From alan.gauld at yahoo.co.uk Tue Jan 2 11:36:54 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 2 Jan 2018 16:36:54 +0000 Subject: [Tutor] checking connection to internet until success In-Reply-To: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com> References: <640efd81-52db-ef77-8931-c8c252c6028b@gmail.com> Message-ID: On 01/01/18 21:38, Pi wrote: > with this code i am getting actual date from internet. I need correct > date, because i am not sure this set on computer is right. The first obvious pointto make is that all modern OS come with an option to read the date/time from an internet time server so this is the correct solution to your problem rather than writing a web scraper. At the very least you should access a time server directly rather than scrape a web site. (try the ntplib module) But if you do want to try doing it yourself... > import requests, time > > try: > ??? OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10] > ??? OffLineDate = time.strftime("%Y-%m-%d")> > ??? if OnLineDate == OffLineDate: > ? ? ? ? do_something > ? ? else: > ? ? ? ? do_something_else > except requests.ConnectionError: > ??? print("Can not connect.") > > > But this code is run once. And i am stuck. Tries with while loop doesnt > took any advance. WE need to see what doesn't work to comment. A while loop with a suitable sleep() should work. But again it's probably better to use the OS to set up a timed job. On Unix this is done either with 'cron' or 'at'. On Windows I believe 'at' is the tool. There are other schedulers available too with GUIs etc. > how check connection to internet to check for every lets say 30 seconds > until success? What is success? When the times match? Or when they don't? Or just whenever you succesfully connect? -- 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 yahoo.co.uk Tue Jan 2 20:39:58 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 3 Jan 2018 01:39:58 +0000 Subject: [Tutor] Fwd: Re: checking connection to internet until success In-Reply-To: <449c5226-29e4-d2b2-d79f-38542abede0a@gmail.com> References: <449c5226-29e4-d2b2-d79f-38542abede0a@gmail.com> Message-ID: Forwarding to list... -------- Forwarded Message -------- Subject: Re: [Tutor] checking connection to internet until success Date: Wed, 3 Jan 2018 01:35:18 +0100 From: Pi To: Alan Gauld 10 months ago i wrote application using time from OS (Windows 7), but my alpha tester found how to trick my app. Thats why i need to use date from web. And success of new application is when code will know, that computer is connected to web and can get actual date. On 02.01.2018? 17:36, Alan Gauld via Tutor wrote: > On 01/01/18 21:38, Pi wrote: >> with this code i am getting actual date from internet. I need correct >> date, because i am not sure this set on computer is right. > The first obvious pointto make is that all modern OS come > with an option to read the date/time from an internet time > server so this is the correct solution to your problem > rather than writing a web scraper. At the very least you > should access a time server directly rather than scrape > a web site. (try the ntplib module) > > But if you do want to try doing it yourself... > >> import requests, time >> >> try: >> ??? OnLineDate = requests.get("http://just-the-time.appspot.com").text[:10] >> ??? OffLineDate = time.strftime("%Y-%m-%d")> >> ??? if OnLineDate == OffLineDate: >> ? ? ? ? do_something >> ? ? else: >> ? ? ? ? do_something_else >> except requests.ConnectionError: >> ??? print("Can not connect.") >> >> >> But this code is run once. And i am stuck. Tries with while loop doesnt >> took any advance. > WE need to see what doesn't work to comment. A while loop > with a suitable sleep() should work. > > But again it's probably better to use the OS to set up > a timed job. > > On Unix this is done either with 'cron' or 'at'. > On Windows I believe 'at' is the tool. > There are other schedulers available too with GUIs etc. > >> how check connection to internet to check for every lets say 30 seconds >> until success? > What is success? When the times match? Or when they don't? > Or just whenever you succesfully connect? > From renukeshnk15 at gmail.com Wed Jan 3 00:31:54 2018 From: renukeshnk15 at gmail.com (renukesh nk) Date: Wed, 3 Jan 2018 11:01:54 +0530 Subject: [Tutor] CSV row and column width automation Message-ID: Hi, Is there any way to automatically set the column and row width in a CSV file through python script From alan.gauld at yahoo.co.uk Wed Jan 3 06:10:11 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 3 Jan 2018 11:10:11 +0000 Subject: [Tutor] CSV row and column width automation In-Reply-To: References: Message-ID: On 03/01/18 05:31, renukesh nk wrote: > Is there any way to automatically set the column and row width in a CSV > file through python script I'm not sure what you mean. CSV files don't have widths, they are just sequences of data strings separated by commas. Each piece of data takes as much space as it needs. You could write code to force the strings to all be the same width as the longest string but that would just be making life harder for yourself when it comes to extracting it again. CSV is a data transport mechanism not a display format. Are you thinking about some kind of display mechanism like a web page table or a spreadsheet perhaps? They have widths. But how you set them is very different so you'd need to tell us what kind of table you have in mind. -- 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 Jan 3 21:20:25 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 3 Jan 2018 20:20:25 -0600 Subject: [Tutor] How to handle passwords in programs that perform FTP processes? Message-ID: Python 2.4, Solaris 10. I have several programs that must transfer files from our Solaris 10-based intranet to our Windows-based intranet. They each have their own shell script to perform these file transfers, each customized for each program. Today I wrote a Python 2 program using the ftplib module that will replace all of these shell script programs and provide a standard interface for doing these transfers. It also will serve as a method for me to backup my programs on the Solaris 10-based intranet to a location on the Windows side. Even though these networks are supposed to be secure intranets where those who need to know know the generic user name and password for the FTP server, I would like to be as secure as possible with this information. How do I go about doing this? I am limited to whatever is available on the Solaris 10 operating system and it must work with Python 2.4 and its available standard libraries. I cannot use any outside software. However, I am free to write all the software I might like, assuming I can find time to do so. What would you sage Pythonistas recommend for my situation? -- boB From cs at cskk.id.au Thu Jan 4 17:24:04 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Fri, 5 Jan 2018 09:24:04 +1100 Subject: [Tutor] How to handle passwords in programs that perform FTP processes? In-Reply-To: References: Message-ID: <20180104222404.GA51412@cskk.homeip.net> On 03Jan2018 20:20, boB Stepp wrote: >Python 2.4, Solaris 10. > >I have several programs that must transfer files from our Solaris >10-based intranet to our Windows-based intranet. They each have their >own shell script to perform these file transfers, each customized for >each program. Today I wrote a Python 2 program using the ftplib >module that will replace all of these shell script programs and >provide a standard interface for doing these transfers. It also will >serve as a method for me to backup my programs on the Solaris 10-based >intranet to a location on the Windows side. Even though these >networks are supposed to be secure intranets where those who need to >know know the generic user name and password for the FTP server, I >would like to be as secure as possible with this information. How do >I go about doing this? I am limited to whatever is available on the >Solaris 10 operating system and it must work with Python 2.4 and its >available standard libraries. I cannot use any outside software. >However, I am free to write all the software I might like, assuming I >can find time to do so. What would you sage Pythonistas recommend for >my situation? Look at the netrc module. Tradition ftp programs used to be able to use .netrc files, and this module reads them. It means storing credentials in the clear (obvious make the .netrc file 0600 permissions), but in most batch situations you're stuck with that anyway. Cheers, Cameron Simpson From alan.gauld at yahoo.co.uk Fri Jan 5 08:49:34 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 5 Jan 2018 13:49:34 +0000 Subject: [Tutor] Updates to web tutor In-Reply-To: References: Message-ID: On 15/11/17 17:41, Alan Gauld via Tutor wrote: > Only just on topic but I'd like some help please... > > I've been doing some much needed maintenance to my web tutor. The latest update is that I think I've got the styling and structure as I want it and everything should be usable on all devices (?!!!) I've now started updating the content and in particular fixing broken links and updating all the MS Windows stuff from XP to Windows 10. So far I've completed up to the end of the Basics section (error handling). I have also completed the last section (on applications) with 4 new topics on web programming and one on concurrent programming(threading and multiprocessing). I'll be working through the remaining topics over the next 2 weeks and aim to move the test site to become the main tutor landing page by the end of the month. As before, if anyone can spare the time to take a look at the new and updated material and send me feedback (offlist) it will be appreciated. -- 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 yahoo.co.uk Fri Jan 5 18:51:40 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 5 Jan 2018 23:51:40 +0000 Subject: [Tutor] Updates to web tutor In-Reply-To: References: Message-ID: On 05/01/18 13:49, Alan Gauld via Tutor wrote: > As before, if anyone can spare the time to take a look at > the new and updated material and send me feedback (offlist) > it will be appreciated. Just realized I forgot to include the test site url! If it's not a yellow theme then it's the wrong site! It should be: http://www.alan-g.me.uk/l2p2 Sorry about 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 robertvstepp at gmail.com Sun Jan 7 01:49:59 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 7 Jan 2018 00:49:59 -0600 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? Message-ID: Win7, Python 3.6.2 If I run a unit test with the following embedded: print('realpath =', os.path.realpath('test_main.py')) I get the following in my test output (Only relevant line is shown): Ensure expected list of string integers is returned. ... realpath = c:\Projects\solitaire_scorekeeper\test_main.py In actuality "test_main.py" is located at "c:\Projects\solitaire_scorekeeper\tests\test_main.py" If I open the interpreter from the directory "c:\Projects\solitaire_scorekeeper\tests\" I get what I expect: py3: import os.path py3: os.path.realpath('test_main.py') 'c:\\Projects\\solitaire_scorekeeper\\tests\\test_main.py' Would someone enlighten me as to why the different results? TIA! -- boB From steve at pearwood.info Sun Jan 7 03:05:59 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 7 Jan 2018 19:05:59 +1100 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: Message-ID: <20180107080558.GC4152@ando.pearwood.info> On Sun, Jan 07, 2018 at 12:49:59AM -0600, boB Stepp wrote: > Win7, Python 3.6.2 > > If I run a unit test with the following embedded: > > print('realpath =', os.path.realpath('test_main.py')) > > I get the following in my test output (Only relevant line is shown): > > Ensure expected list of string integers is returned. ... > realpath = c:\Projects\solitaire_scorekeeper\test_main.py realpath() returns the canonical path of the given filename. It doesn't try to locate some actual existing file. The fact that there is a file called "test_main.py" located here: > In actuality "test_main.py" is located at > "c:\Projects\solitaire_scorekeeper\tests\test_main.py" is irrelevent. You asked for the "real" (canonical) path name to the relative pathname "test_main.py". That means in the current directory, which apparently is C:\Projects\solitaire_scorekeeper. Hence you get the result C:\Projects\solitaire_scorekeeper\test_main.py even though the "real file" is one directory further in. > If I open the interpreter from the directory > "c:\Projects\solitaire_scorekeeper\tests\" I get what I expect: Indeed, because now the current directory is different. I think you may be confused because you think realpath() has something to do with actual existing files. It doesn't. Remember that realpath() isn't just called on existing files, it may be called on arbitrary file names which don't exist. Its more like os.path.abspath() except that if the path contains symbolic links (not likely on Windows, but possible) they will be resolved to their real path. -- Steve From robertvstepp at gmail.com Sun Jan 7 04:07:26 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 7 Jan 2018 03:07:26 -0600 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: <20180107080558.GC4152@ando.pearwood.info> References: <20180107080558.GC4152@ando.pearwood.info> Message-ID: On Sun, Jan 7, 2018 at 2:05 AM, Steven D'Aprano wrote: > On Sun, Jan 07, 2018 at 12:49:59AM -0600, boB Stepp wrote: > >> Win7, Python 3.6.2 >> >> If I run a unit test with the following embedded: >> >> print('realpath =', os.path.realpath('test_main.py')) >> >> I get the following in my test output (Only relevant line is shown): >> >> Ensure expected list of string integers is returned. ... >> realpath = c:\Projects\solitaire_scorekeeper\test_main.py > > > realpath() returns the canonical path of the given filename. It doesn't > try to locate some actual existing file. The fact that there is a file > called "test_main.py" located here: > >> In actuality "test_main.py" is located at >> "c:\Projects\solitaire_scorekeeper\tests\test_main.py" > > is irrelevent. You asked for the "real" (canonical) path name to the > relative pathname "test_main.py". That means in the current directory, > which apparently is C:\Projects\solitaire_scorekeeper. Hence you get the > result C:\Projects\solitaire_scorekeeper\test_main.py even though the > "real file" is one directory further in. After some searching I have yet to locate a definition of "canonical path" that makes sense to me. The dictionary definition of canonical does not seem to be very helpful in understanding this. Can you clarify this? What is the methodology that os.path.realpath(path) is actually following to yield a particular path name? And why does it not care if path refers to a real file or not? What I *really* want to do is locate and open a file "test_data.dat" that is in the same directory as the file with the tests, "tests/test_main.py". I asked a related question a while back but I now suspect I did not fully get everything. I have recently been experimenting with the os and os.path modules and thought I had found the magic bullet with os.path.realpath(). Anyway, based on that earlier related question and your answer tonight I have modified my test class to the following: class TestOpenFileStrIntsToList(unittest.TestCase): """Tests for the function open_file_str_ints_to_list.""" def test_open_file_str_ints_to_list(self): """Ensure expected list of string integers is returned.""" path = os.path.dirname( os.path.realpath(__file__)) + '/test_data.dat' print('realpath =', os.path.realpath(__file__)) expected_list = ['-3', '-2', '-1', '0', '1', '2', '3'] self.assertEqual(open_file_str_ints_to_list(path), expected_list) The test_data file is just the expected_list values, one value per line in the file. The function being tested is: def open_file_str_ints_to_list(path): """Given a path to the file, open this file containing one string integer per line, and convert it to a list of string integers, which is then returned by this function.""" with open(path) as infile: string_integers = [line.strip() for line in infile] return string_integers BTW, I am having trouble coming up with a good name for a string that looks like an integer that I plan on using int() later to convert the string to an integer. "String integer" is my best thought at this time. Anyway, the print() statement in the test case is giving me the correct result. Is this way of determining the directory which test_main.py is running from bullet proof? -- boB From sjeik_appie at hotmail.com Sun Jan 7 05:51:20 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Sun, 7 Jan 2018 10:51:20 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? Message-ID: On Jan 7, 2018 09:08, Steven D'Aprano wrote: > > On Sun, Jan 07, 2018 at 12:49:59AM -0600, boB Stepp wrote: > > > Win7, Python 3.6.2 > > > > If I run a unit test with the following embedded: > > > > print('realpath =', os.path.realpath('test_main.py')) > > > > I get the following in my test output (Only relevant line is shown): > > > > Ensure expected list of string integers is returned. ... > > realpath = c:\Projects\solitaire_scorekeeper\test_main.py > > > realpath() returns the canonical path of the given filename. It doesn't > try to locate some actual existing file. I always thought that os.path.realpath is the Python equivalent of Linux realpath/readlink (http://man7.org/linux/man-pages/man3/realpath.3.html). And that, thus, there's only a difference between input and output when the input is a symlink (and maybe also when it's a hard link - in this case the function actually also does something in Windows). But then, I don't really know the meaning of the word "canonical", to tell you the truth (maybe #4 in http://www.dictionary.com/browse/canonical) From alan.gauld at yahoo.co.uk Sun Jan 7 09:32:38 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 7 Jan 2018 14:32:38 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> Message-ID: On 07/01/18 09:07, boB Stepp wrote: > clarify this? What is the methodology that os.path.realpath(path) is > actually following to yield a particular path name? And why does it > not care if path refers to a real file or not? The os.path module is mostly a string manipulation toolkit. It checks that a string looks like a path and it de/constructs paths from strings. But it does not pay muchy(any?) attention to the filesystem. It doesn't care if the paths it deals with are real paths or not, its purely manipulating the strings according to the syntax rules for paths. The exceptions are the test functions like isfile(), isdir() etc. > What I *really* want to do is locate and open a file "test_data.dat" > that is in the same directory as the file with the tests, For that you need to do some work with listdir or glob. You might need to do a os.getcwd() but I suspect it will return the folder where you started te program rather than the folder the file lives in. For that you may need to use the __file__ attribute of the test module. So something like: dir = os.path.dirname(__file__) # assuming this is in the test module fn = os.path.join(dir,fname) if os.path.isfile(fn) # check the file actually exists f = open(fn) > class TestOpenFileStrIntsToList(unittest.TestCase): > """Tests for the function open_file_str_ints_to_list.""" > > def test_open_file_str_ints_to_list(self): > """Ensure expected list of string integers is returned.""" > > path = os.path.dirname( > os.path.realpath(__file__)) + '/test_data.dat' > print('realpath =', os.path.realpath(__file__)) Yes, thats it although you could test using isfile() or better still use a try/except around the open. Also you should strictly use os.path.join() to create the path > BTW, I am having trouble coming up with a good name for a string that > looks like an integer that I plan on using int() later to convert the > string to an integer. "String integer" is my best thought at this > time. What's it for? Where did it come from? type based names are rarely good, better to describe why/where. input_Id, read_Id, stored_Id etc.... Or substitute Ref, or Count or whatever for Id. Then the real int var name becomes the second part: Id = int(input_Id) or count = int(stored_count) > Is this way of determining the directory which > test_main.py is running from bullet proof? If its really in the same folder then I believe so - or as bullet proof as it gets. Maybe if you create a shortcut to the real folder etc you might need to revert to realpath. -- 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 Jan 7 17:56:52 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 7 Jan 2018 16:56:52 -0600 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: Message-ID: On Sun, Jan 7, 2018 at 4:51 AM, Albert-Jan Roskam wrote: > > On Jan 7, 2018 09:08, Steven D'Aprano wrote: >> realpath() returns the canonical path of the given filename. It doesn't >> try to locate some actual existing file. > > I always thought that os.path.realpath is the Python equivalent of Linux realpath/readlink (http://man7.org/linux/man-pages/man3/realpath.3.html). And that, thus, there's only a difference between input and output when the input is a symlink (and maybe also when it's a hard link - in this case the function actually also does something in Windows). But then, I don't really know the meaning of the word "canonical", to tell you the truth (maybe #4 in http://www.dictionary.com/browse/canonical) My hangup was mostly that I was assuming that an actually existing path to a real file was implied. Apparently that is not the case. So Alan's explanation has cleared that up for me (I think!). I agree with you that the 4th definition you cite: "4. Mathematics. (of an equation, coordinate, etc.) in simplest or standard form." is the most sensible definition in this context with Steve's caveats. -- boB From steve at pearwood.info Sun Jan 7 18:38:50 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 8 Jan 2018 10:38:50 +1100 Subject: [Tutor] Testing Message-ID: <20180107233850.GI6667@ando.pearwood.info> I've tried emailing in response to the os.path.realpath thread twice, and neither email has made it through. Alan, am I stuck in the moderator queue for some reason? -- Steve From robertvstepp at gmail.com Sun Jan 7 19:17:33 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 7 Jan 2018 18:17:33 -0600 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> Message-ID: On Sun, Jan 7, 2018 at 8:32 AM, Alan Gauld via Tutor wrote: > On 07/01/18 09:07, boB Stepp wrote: >> clarify this? What is the methodology that os.path.realpath(path) is >> actually following to yield a particular path name? And why does it >> not care if path refers to a real file or not? > > The os.path module is mostly a string manipulation toolkit. This is the critical piece that was eluding me. I assumed that the actual file system was being queried, checked and expanded as needed. > It checks that a string looks like a path and it de/constructs > paths from strings. But it does not pay muchy(any?) attention > to the filesystem. It doesn't care if the paths it deals > with are real paths or not, its purely manipulating the > strings according to the syntax rules for paths. I was assuming it was computing the actual path to the file given as its argument. Steve's comments make much more sense now as well as the "canonical" aspect. >> class TestOpenFileStrIntsToList(unittest.TestCase): >> """Tests for the function open_file_str_ints_to_list.""" >> >> def test_open_file_str_ints_to_list(self): >> """Ensure expected list of string integers is returned.""" >> >> path = os.path.dirname( >> os.path.realpath(__file__)) + '/test_data.dat' >> print('realpath =', os.path.realpath(__file__)) > > Yes, thats it although you could test using isfile() or > better still use a try/except around the open. > > Also you should strictly use os.path.join() to create the path Duly noted on os.path.join(). I have not gotten to thinking about the UI yet, and don't mind if a file not found error is generated here in the testing code as it will let me know I've screwed something up. This is strictly a play project to record my manual games of solitaire. I doubt it will be useful to anyone else. Once I get to coding the UI I might wrap this in a try/except if I feel I would gain any benefit from handling the exception. >> BTW, I am having trouble coming up with a good name for a string that >> looks like an integer that I plan on using int() later to convert the >> string to an integer. "String integer" is my best thought at this >> time. > > What's it for? Where did it come from? > type based names are rarely good, better to describe why/where. > > input_Id, read_Id, stored_Id etc.... > > Or substitute Ref, or Count or whatever for Id. > > Then the real int var name becomes the second part: > > Id = int(input_Id) > > or > > count = int(stored_count) The above has just now led me to a Homer Simpson "Doh!" moment. When I open the file and covert it to a list of "string" integers I currently have: with open(path) as infile: string_integers = [line.strip() for line in infile] and then run the list through another function to get an integer list. Why on earth didn't I just write: with open(path) as infile: total_scores = [int(line.strip()) for line in infile] which directly creates what I want directly? [Please don't answer this question! ~(:>)) ] -- boB From robertvstepp at gmail.com Sun Jan 7 19:24:44 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Sun, 7 Jan 2018 18:24:44 -0600 Subject: [Tutor] Testing In-Reply-To: <20180107233850.GI6667@ando.pearwood.info> References: <20180107233850.GI6667@ando.pearwood.info> Message-ID: On Sun, Jan 7, 2018 at 5:38 PM, Steven D'Aprano wrote: > I've tried emailing in response to the os.path.realpath thread twice, > and neither email has made it through. > > Alan, am I stuck in the moderator queue for some reason? This one made it through. My original answer to your post last night took so long to appear on https://mail.python.org/pipermail/tutor that I finally gave up and went to bed. But it was there when I awoke today! -- boB From alan.gauld at yahoo.co.uk Sun Jan 7 19:39:07 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 8 Jan 2018 00:39:07 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> Message-ID: On 08/01/18 00:17, boB Stepp wrote: >> The os.path module is mostly a string manipulation toolkit. > > This is the critical piece that was eluding me. I assumed that the > actual file system was being queried, checked and expanded as needed. To be fair realpath() does do a tiny bit of magic in that it checks if the file (or any part of the path) is a link (aka shortcut) and tries to give you the actual path to the original file - ie it follows the link. I'm not sure how effective it is, I've only played with it but never used it in earnest. But in general I tend not to rely on os.path doing anything remotely clever. -- 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 Jan 7 20:21:49 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 8 Jan 2018 12:21:49 +1100 Subject: [Tutor] Testing In-Reply-To: <3cfe3325-9fe4-d495-f809-a97cb2e57066@yahoo.co.uk> References: <20180107233850.GI6667@ando.pearwood.info> <3cfe3325-9fe4-d495-f809-a97cb2e57066@yahoo.co.uk> Message-ID: <20180108012146.GJ6667@ando.pearwood.info> On Mon, Jan 08, 2018 at 12:31:06AM +0000, Alan Gauld wrote: > On 07/01/18 23:38, Steven D'Aprano wrote: > > I've tried emailing in response to the os.path.realpath thread twice, > > and neither email has made it through. > > > > Alan, am I stuck in the moderator queue for some reason? > > Nope, nothing from you there. > > And your account settings all look fine. I've made another attempt to send through my response to the realpath thread. -- Steve From steve at pearwood.info Mon Jan 8 01:47:00 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Mon, 8 Jan 2018 17:47:00 +1100 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> Message-ID: <20180108064700.GL6667@ando.pearwood.info> On Mon, Jan 08, 2018 at 12:39:07AM +0000, Alan Gauld via Tutor wrote: > To be fair realpath() does do a tiny bit of magic in that it > checks if the file (or any part of the path) is a link (aka > shortcut) and tries to give you the actual path to the > original file - ie it follows the link. As I actually explained in my previous email, the one which has disappeared into the aether, realpath resolves symbolic links and replaces them by the real path they represent. But that's only on Unix/Linux/Mac, on Windows it does not. Symbolic links, however, are *not* Windows shortcuts. Windows shortcuts are just a special sort of file, one which the Windows file explorer treats as an alias to another file or folder. Symbolic links on Unix are a feature of the file system itself, not a kind of file. What's the difference? With a shortcut, if you tell Python or some other program to open a shortcut, it will treat it as an ordinary file (because that's what it is!) and read from the shortcut file itself. Only programs like Windows Explorer which have been specially programmed to follow shortcuts will do so. But with a symbolic link, programs don't need to know anything about them. If you have a link: /A/link ---> /B/C/file then *any* program will treat opening /A/link as if it were /B/C/file. In other words: - under Windows, a shortcut is a regular file, unless the programmer takes special action to treat it as an alias; - under Unix, a symbolic link is an alias, unless the programmer takes special action to treat it as a symbolic link. (Aside: starting with Windows Vista, NTFS also supports symbolic links, like Unix. But few Windows users know this, or use them.) -- Steve From eryksun at gmail.com Mon Jan 8 08:28:11 2018 From: eryksun at gmail.com (eryk sun) Date: Mon, 8 Jan 2018 13:28:11 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: Message-ID: On Sun, Jan 7, 2018 at 10:51 AM, Albert-Jan Roskam wrote: > > On Jan 7, 2018 09:08, Steven D'Aprano wrote: >> >> realpath() returns the canonical path of the given filename. It doesn't >> try to locate some actual existing file. > > I always thought that os.path.realpath is the Python equivalent of Linux > realpath/readlink In POSIX, os.path.realpath resolves a path that contains symlinks by calling os.readlink in a loop until all links are resolved. In Windows, os.path.realpath is an alias for os.path.abspath. This decision predates NTFS support for junctions (2000) and symbolic links (Vista). It's simply the case that no one has gotten around to implementing realpath for Windows. In Windows, os.path.abspath calls os.path._getfullpathname (WinAPI GetFullPathName). Other than resolving the working directory, this is a string transformation to return a canonical, fully-qualified path. It doesn't touch the filesystem. Note that in the case of classic DOS devices, the canonical path is a local-device path (i.e. "\\.\" prefix). For example: >>> print(os.path.abspath('C:/path/to/nul')) \\.\nul > maybe also when it's a hard link - in this case the function actually also does > something in Windows A hard link shouldn't be resolved to another path by os.path.realpath. It's already a real path. Cross-platform Python 3 code that needs to resolve symbolic links (or junctions) can use pathlib.Path.resolve(). For example: >>> pathlib.Path('C:/Documents and Settings').resolve() WindowsPath('C:/Users') On Windows this relies on os.path._getfinalpathname (WinAPI GetFinalPathNameByHandle). This function returns the final opened filename, so the OS does all of the work to resolve the final path. In non-strict mode pathlib uses a loop to reduce the path when it can't be resolved to an existing file. (There are open issues for edge cases in this code, but it should work as intended with regular files in accessible directories.) For those who are curious, WinAPI GetFinalPathNameByHandle is called with a handle for a File object that's opened via CreateFile. It gets the NT name of the volume (e.g, "\Device\HarddiskVolume1") and the filesystem path (e.g. "\Users"). Then it asks the mount-point manager to map this NT name back to a DOS name such as drive "C:"; or an NTFS volume mountpoint such as "C:\Mount\VolumeName"; or a "Volume{GUID}" name. (In the latter case, Python's _getfinalpathname and pathlib have bugs and need improvement.) From steve at pearwood.info Tue Jan 9 03:47:33 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 9 Jan 2018 19:47:33 +1100 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> Message-ID: <20180109084733.GG4152@ando.pearwood.info> On Sun, Jan 07, 2018 at 03:07:26AM -0600, boB Stepp wrote: > After some searching I have yet to locate a definition of "canonical > path" that makes sense to me. The dictionary definition of canonical > does not seem to be very helpful in understanding this. Probably the best definition would be "the simplest authoritative form of the path". > What is the methodology that os.path.realpath(path) is > actually following to yield a particular path name? Trust the Source, Luke :-) The Python 3.5 source code for os.path.realpath under Windows looks like this: # realpath is a no-op on systems without islink support realpath = abspath The comment is misleading[1] for two reasons: - it isn't a no-op, since abspath() actually does something; what they mean is that on Windows realpath() doesn't do anything beyond what abspath() does; (on Linux and Mac, it also checks for symbolic links, and converts them to their actual paths) - and technically speaking, some Windows file systems *do* support symbolic links, although few people know this or use them. https://en.wikipedia.org/wiki/NTFS_symbolic_link Nevertheless, we can say that under Windows realpath() does nothing more than abspath() (at least up to Python 3.5). So what does abspath() do? The source for abspath() is a more little complicated, because it has two different implementations depending on whether you are *actually* running Windows or not. But basically, abspath() does this: - if the path is a relative path (does not start with C:\ or similar) then prepend the current directory to the path; - then normalise the path. What does it mean to normalise the path? It converts it to the simplest form, eliminating redundant slashes and dots. Because this is Windows, there are a bunch of special cases for device names and literal paths (whatever they are!) that look like this: \\.\ -> device names \\?\ -> literal paths but for the standard case of ordinary file names, normpath() on Windows will convert forward slashes / to backslashes \ and eliminate duplicated slashes and dots in the path. Remember that . means "this directory" and .. means "one directory up", normpath() will normalise any of these: A//B A/./B A/foo/../B to A\B. Since the Windows version of realpath() doesn't care about symbolic links, it doesn't need to care whether any of the directories and files actually exist or not. All it needs to do is turn a relative path into an absolute path, then normalise the path. And none of that depends on the path actually existing. > What I *really* want to do is locate and open a file "test_data.dat" > that is in the same directory as the file with the tests, > "tests/test_main.py". If you can assume that tests/test_main.py is always in the current directory, then you can just write: PATH = 'tests/test_main.py' and use that. open(PATH) will happily work on relative paths as well as absolute. Reminder: absolute paths start with a drive: A:\foo\bar relative paths don't, and so they implicitly start in the current directory. *But* that assumes that you have started running the tests from inside the directory which includes tests/test_main.py. That might not be the case. In order to solve this problem properly, I think we need to know how your project is laid out, including the tests. But my guess is that the solution is to extract the path of the running module, and append tests/test_main.py to that path. If this isn't clear, ask and I'll explain in more detail. (But later, I'm about to move off the computer for a few hours.) > Anyway, based on that > earlier related question and your answer tonight I have modified my > test class to the following: [...] I'll read it later. [1] "At Resolver we've found it useful to short-circuit any doubt and just refer to comments in code as 'lies'. " --Michael Foord paraphrases Christian Muirhead on python-dev, 2009-03-22 -- Steve From steve at pearwood.info Tue Jan 9 03:49:40 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Tue, 9 Jan 2018 19:49:40 +1100 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> <20180108064700.GL6667@ando.pearwood.info> Message-ID: <20180109084939.GQ6667@ando.pearwood.info> On Mon, Jan 08, 2018 at 05:08:49PM -0600, boB Stepp wrote: > Hi Steve, > > On Mon, Jan 8, 2018 at 12:47 AM, Steven D'Aprano wrote: > > > As I actually explained in my previous email, the one which has > > disappeared into the aether, ... > > Do you still have the email you sent? I would like to read it if you > don't mind sending it to me. Mystery solved. I've been sending to the wrong email address... Fixed now, and re-sent to the list. -- Steve From sjeik_appie at hotmail.com Tue Jan 9 09:48:16 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Tue, 9 Jan 2018 14:48:16 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: <20180109084733.GG4152@ando.pearwood.info> References: <20180107080558.GC4152@ando.pearwood.info> , <20180109084733.GG4152@ando.pearwood.info> Message-ID: From: Tutor on behalf of Steven D'Aprano Sent: Tuesday, January 9, 2018 8:47 AM To: tutor at python.org Subject: Re: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? ? > The Python 3.5 source code for os.path.realpath under Windows looks like > this: > ># realpath is a no-op on systems without islink support > realpath = abspath D?j?-vu [1], but I think that it would be a great enhancement if os.realpath would return the UNC path if given a mapped drive in Windows, if needed as extended path (prefixed with "\\?\UNC\"). That's something I use all the time, unlike symlinks, in Windows. And I would also welcome a convenience function in the os.path module that does expanduser, expandvars, normpath, realpath, and maybe more. I haven't used pathlib yet. Will os.path development some day be frozen so pathlib becomes the standard? It seems to be nicer. [1] http://python.6.x6.nabble.com/Tutor-getUncPath-mappedDrive-td4652304.html From tsu.yubo at gmail.com Tue Jan 9 09:20:14 2018 From: tsu.yubo at gmail.com (YU Bo) Date: Tue, 9 Jan 2018 22:20:14 +0800 Subject: [Tutor] delete strings from specificed words Message-ID: <20180109142008.aduremugxw7ufmby@debian.debian> Hi, I am learning python to reslove issue,which make happy:) But, i am facing an interesting question.I have no idea to deal with it. The text i will working as follow: ```text [PATCH] perf tools: Fix copyfile_offset update of output offset We need to increase output offset in each iteration, not decrease it as we currently do. I guess we were lucky to finish in most cases in first iteration, so the bug never showed. However it shows a lot when working with big (~4GB) size data. Link: http://lkml.kernel.org/n/tip-f4az7t2nxjbjz5tqrv83z64e at xxxxxxxxxxxxxx Signed-off-by: Jiri Olsa --- tools/perf/util/util.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c index a789f952b3e9..443892dabedb 100644 --- a/tools/perf/util/util.c +++ b/tools/perf/util/util.c @@ -210,7 +210,7 @@ static int copyfile_offset(int ifd, loff_t off_in, int ofd, loff_t off_out, u64 size -= ret; off_in += ret; - off_out -= ret; + off_out += ret; } munmap(ptr, off_in + size); -- 2.13.6 ``` In fact, this is a patch from lkml,my goal is to design a kernel podcast for myself to focus on what happened in kernel. I have crawled the text with python and want to remove strings from *diff --git*, because reading the git commit above, i have a shape in head. I have tried split(), replace(), but i have no idea to deal with it. I will appericate if you have any idea. Thanks! From alan.gauld at yahoo.co.uk Tue Jan 9 17:25:11 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 9 Jan 2018 22:25:11 +0000 Subject: [Tutor] delete strings from specificed words In-Reply-To: <20180109142008.aduremugxw7ufmby@debian.debian> References: <20180109142008.aduremugxw7ufmby@debian.debian> Message-ID: On 09/01/18 14:20, YU Bo wrote: > But, i am facing an interesting question.I have no idea to deal with it. I don;t think you have given us enough context to be able to help much. WE would need some idea of the input and output data (both current and desired) > [PATCH] perf tools: Fix copyfile_offset update of output offset > > We need to increase output offset in each iteration, > not decrease it as we currently do. > It sounds like you are building some kind of pretty printer. Maybe you could use Pythons pretty-print module as a design template? Or maybe even use some of it directly. It just depends on your data formats etc. > In fact, this is a patch from lkml,my goal is to design a kernel podcast > for myself to focus on what happened in kernel. Sorry, I've no idea what lkml is nor what kernel you are talking about. Can you show us what you are receiving, what you are currently producing and what you are trying to produce? Some actual code might be an idea too. And the python version and OS. -- 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 Tue Jan 9 22:56:16 2018 From: eryksun at gmail.com (eryk sun) Date: Wed, 10 Jan 2018 03:56:16 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> <20180109084733.GG4152@ando.pearwood.info> Message-ID: On Tue, Jan 9, 2018 at 2:48 PM, Albert-Jan Roskam wrote: > > I think that it would be a great enhancement if os.realpath would return the UNC path if > given a mapped drive in Windows, if needed as extended path (prefixed with "\\?\UNC\"). > That's something I use all the time, unlike symlinks, in Windows. pathlib can do this for you, or call os.path._getfinalpathname. I recently helped someone that wanted the reverse, to map the resolved UNC path back to a logical drive: https://bugs.python.org/issue32442 > And I would also welcome a convenience function in the os.path module that does > expanduser, expandvars, normpath, realpath, and maybe more. pathlib implements expanduser, but it's still lame on Windows for a user other than the current user. It assumes all user profiles are in the same directory instead of directly getting the user's profile path. Anyway, expanduser is of limited use. We can't assume in general that a user's special folders (e.g. Desktop, Documents) are in the default location relative to the profile directory. Almost all of them are relocatable. There are shell APIs to look up the current locations, such as SHGetKnownFolderPath. This can be called with ctypes [1]. For users other than the current user, it requires logging on and impersonating the user, which requires administrator access. [1]: https://stackoverflow.com/a/33181421/205580 You can log a user on without a password by calling LsaLogonUser to request an MSV1 S4U (service for user) logon. The access token will only be identification level, unless the script is running as a SYSTEM service. But identification level is enough to query the location of a user's known folders. I don't recommended calling LsaLogonUser via ctypes if you have the option to write an extension module in C/C++, but I did manage to get it working with ctypes [2]. For example: >>> from security_lsa import logon_msv1_s4u >>> from knownfolders import FOLDERID, get_known_folder_path >>> logon_info = logon_msv1_s4u('Administrator') >>> get_known_folder_path(FOLDERID.Desktop, logon_info.Token) 'C:\\Users\\Administrator\\Desktop' [2]: https://stackoverflow.com/a/43233332/205580 Also, please don't use expanduser to enable applications to spam the profile directory with configuration files and directories. Use the local and roaming application data directories. From tsu.yubo at gmail.com Tue Jan 9 22:45:23 2018 From: tsu.yubo at gmail.com (YU Bo) Date: Wed, 10 Jan 2018 11:45:23 +0800 Subject: [Tutor] delete strings from specificed words In-Reply-To: References: <20180109142008.aduremugxw7ufmby@debian.debian> Message-ID: <20180110034521.twc73s25xrxsqr77@debian.debian> Hi, First, thank you very much for your reply. On Tue, Jan 09, 2018 at 10:25:11PM +0000, Alan Gauld via Tutor wrote: >On 09/01/18 14:20, YU Bo wrote: > >> But, i am facing an interesting question.I have no idea to deal with it. > >I don;t think you have given us enough context to >be able to help much. WE would need some idea of >the input and output data (both current and desired) > >> > >It sounds like you are building some kind of pretty printer. >Maybe you could use Pythons pretty-print module as a design >template? Or maybe even use some of it directly. It just >depends on your data formats etc. Yes. I think python can deal with it directly. > >> In fact, this is a patch from lkml,my goal is to design a kernel podcast >> for myself to focus on what happened in kernel. > >Sorry, I've no idea what lkml is nor what kernel you are talking about. > >Can you show us what you are receiving, what you are >currently producing and what you are trying to produce? > >Some actual code might be an idea too. >And the python version and OS. Sorry, i don't to explain it.But, my code is terribly. lkml.py: ```code #!/usr/bin/python # -*- coding: UTF-8 -*- # File Name: lkml.py # Author: Bo Yu """ This is source code in page that i want to get """ import sys reload(sys) sys.setdefaultencoding('utf8') import urllib2 from bs4 import BeautifulSoup import requests import chardet import re # import myself print function from get_content import print_content if __name__ == '__main__': comment_url = [] target = 'https://www.spinics.net/lists/kernel/threads.html' req = requests.get(url=target) req.encoding = 'utf-8' content = req.text bf = BeautifulSoup(content ,'lxml') # There is no problem context = bf.find_all('strong') for ret in context[0:1]: for test in ret: print '\t' x = re.split(' ', str(test)) y = re.search('"(.+?)"', str(x)).group(1) comment_url.append(target.replace("threads.html", str(y))) for tmp_target in comment_url: print "===This is a new file ===" print_content(tmp_target, 'utf-8', 'title') ``` get_content.py: ```code #!/usr/bin/python # -*- coding: UTF-8 -*- # File Name: get_content.py import urllib2 from bs4 import BeautifulSoup import requests import chardet import re def print_content(url, charset, find_id): req = requests.get(url=url) req.encoding = charset content = req.text bf = BeautifulSoup(content ,'lxml') article_title = bf.find('h1') #author = bf.find_all('li') commit = bf.find('pre') print '\t' print article_title.get_text() print '\t' x = str(commit.get_text()) print x ``` python --version: Python 2.7.13 OS: debian 9 usage: python lkml.py output: oh... https://pastecode.xyz/view/04645424 Please ignore my print debug format. This is my code and i can get text like output above. So, simple my quzz: I dont know how to delete strings after special word, for example: ```text The registers rax, rcx and rdx are touched when controlling IBRS so they need to be saved when they can't be clobbered. diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h index 45a63e0..3b9b238 100644 ... ``` I want to delete string from *diff --git* to end, because too many code is here Whatever, 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 > > >_______________________________________________ >Tutor maillist - Tutor at python.org >To unsubscribe or change subscription options: >https://mail.python.org/mailman/listinfo/tutor From __peter__ at web.de Wed Jan 10 04:37:09 2018 From: __peter__ at web.de (Peter Otten) Date: Wed, 10 Jan 2018 10:37:09 +0100 Subject: [Tutor] delete strings from specificed words References: <20180109142008.aduremugxw7ufmby@debian.debian> <20180110034521.twc73s25xrxsqr77@debian.debian> Message-ID: YU Bo wrote: > ```text > The registers rax, rcx and rdx are touched when controlling IBRS > so they need to be saved when they can't be clobbered. > > diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h > index 45a63e0..3b9b238 100644 > ... > ``` > I want to delete string from *diff --git* to end, because too many code is > here Use str.split() or str.partition() and only keep the first part: >>> text = """The registers rax, rcx and rdx are touched when controlling IBRS ... so they need to be saved when they can't be clobbered. ... ... diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h ... index 45a63e0..3b9b238 100644 ... """ >>> cleaned_text = text.partition("diff --git")[0].strip() >>> print(cleaned_text) The registers rax, rcx and rdx are touched when controlling IBRS so they need to be saved when they can't be clobbered. From tsu.yubo at gmail.com Wed Jan 10 07:22:24 2018 From: tsu.yubo at gmail.com (YU Bo) Date: Wed, 10 Jan 2018 20:22:24 +0800 Subject: [Tutor] delete strings from specificed words In-Reply-To: References: <20180109142008.aduremugxw7ufmby@debian.debian> <20180110034521.twc73s25xrxsqr77@debian.debian> Message-ID: <20180110122221.sf4r2674o5nfqog2@debian.debian> Hi, On Wed, Jan 10, 2018 at 10:37:09AM +0100, Peter Otten wrote: >YU Bo wrote: > >> index 45a63e0..3b9b238 100644 >> ... >> ``` >> I want to delete string from *diff --git* to end, because too many code is >> here > >Use str.split() or str.partition() and only keep the first part: > >>>> text = """The registers rax, rcx and rdx are touched when controlling >IBRS >... so they need to be saved when they can't be clobbered. >... >... diff --git a/arch/x86/entry/calling.h b/arch/x86/entry/calling.h >... index 45a63e0..3b9b238 100644 >... """ >>>> cleaned_text = text.partition("diff --git")[0].strip() >>>> print(cleaned_text) >The registers rax, rcx and rdx are touched when controlling IBRS >so they need to be saved when they can't be clobbered. Cool,It is what i want. Thanks all! Bo > > >_______________________________________________ >Tutor maillist - Tutor at python.org >To unsubscribe or change subscription options: >https://mail.python.org/mailman/listinfo/tutor From sjeik_appie at hotmail.com Wed Jan 10 07:59:32 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Wed, 10 Jan 2018 12:59:32 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> <20180109084733.GG4152@ando.pearwood.info> , Message-ID: From: eryk sun Sent: Wednesday, January 10, 2018 3:56 AM To: tutor at python.org Cc: Albert-Jan Roskam Subject: Re: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? ? On Tue, Jan 9, 2018 at 2:48 PM, Albert-Jan Roskam wrote: > >> I think that it would be a great enhancement if os.realpath would return the UNC path if >> given a mapped drive in Windows, if needed as extended path (prefixed with "\\?\UNC\"). >> That's something I use all the time, unlike symlinks, in Windows. > >pathlib can do this for you, or call os.path._getfinalpathname. I tried: >>> from os.path import _getfullpathname >>> _getfullpathname(r"H:") 'h:\\path\\to\\folder' >>> import os >>> os.getcwd() 'h:\\path\\to\\folder' I expected h:\ to be \\server\share\foo. The fact that the current working directory was returned was even more unexpected. >>I recently helped someone that wanted the reverse, to map the resolved >>UNC path back to a logical drive: Oh dear. Why would anybody *want* the drive letters? They are only useful because (a) they save on keystrokes (b) they bypass the annoying limitation of the cd command on windows, ie. it does not work with UNC paths. Driveletter-->UNC conversion is useful when e.g. logging file paths. I do wonder whether the method used to assign the drive letter matters with the . I know net use, pushd, subst. I use 'net use' for more or less permanent drives and pushd/popd to get a temporary drive, available letter (cd nuisance). >We can't assume in general that a user's special folders (e.g. >Desktop, Documents) are in the default location relative to the >profile directory. Almost all of them are relocatable. There are shell >APIs to look up the current locations, such as SHGetKnownFolderPath. >This can be called with ctypes [1]. For users other than the current >user, it requires logging on and impersonating the user, which >requires administrator access. > >[1]: https://stackoverflow.com/a/33181421/205580 Interesting code! I have used the following, which uses SHGetFolderPath, ie. without 'Known'. from win32com.shell import shell, shellcon desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0) Working with ctypes.wintypes is quite complex! From sjeik_appie at hotmail.com Wed Jan 10 11:08:04 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Wed, 10 Jan 2018 16:08:04 +0000 Subject: [Tutor] question about metaclasses Message-ID: Hi, In another thread on this list I was reminded of types.SimpleNamespace. This is nice, but I wanted to create a bag class with constants that are read-only. My main question is about example #3 below (example #2 just illustrates my thought process). Is this a use case to a metaclass? Or can I do it some other way (maybe a class decorator?). I would like to create a metaclass that converts any non-special attributes (=not starting with '_') into properties, if needed. That way I can specify my bag class in a very clean way: I only specify the metaclass, and I list the attributes as normal attrbutes, because the metaclass will convert them into properties. Why does following the line (in #3) not convert the normal attribute into a property? setattr(cls, attr, property(lambda self: obj)) # incorrect! # 1------------------------------------------------- # nice, but I want the constants to be read-only from types import SimpleNamespace const = SimpleNamespace(YES=1, NO=0, DUNNO=9) const.YES = 0 print(const) # 2------------------------------------------------- # works, but I wonder if there's a builtin way class Const(object): """Adding attributes is ok, modifying them is not""" YES = property(lambda self: 1) NO = property(lambda self: 0) DUNNO = property(lambda self: 42) #THROWS_ERROR = 666 def __new__(cls): for attr in dir(cls): if attr.startswith('_'): continue elif not isinstance(getattr(cls, attr), property): raise ValueError("Only properties allowed") return super().__new__(cls) def __repr__(self): kv = ["%s=%s" % (attr, getattr(self, attr)) for \ attr in sorted(dir(Const)) if not attr.startswith('_')] return "ReadOnlyNamespace(" + ", ".join(kv) + ")" c = Const() print(repr(c)) #c.YES = 42 # raises AttributeError (desired behavior) print(c.YES) # 3------------------------------------------------- class Meta(type): def __new__(cls, name, bases, attrs): for attr, obj in attrs.items(): if attr.startswith('_'): continue elif not isinstance(obj, property): import pdb;pdb.set_trace() #setattr(cls, attr, property(lambda self: obj)) # incorrect! raise ValueError("Only properties allowed") return super().__new__(cls, name, bases, attrs) class MyReadOnlyConst(metaclass=Meta): __metaclass__ = Meta YES = property(lambda self: 1) NO = property(lambda self: 0) DUNNO = property(lambda self: 42) THROWS_ERROR = 666 c2 = MyReadOnlyConst() print(c2.THROWS_ERROR) #c2.THROWS_ERROR = 777 #print(c2.THROWS_ERROR) Thank you in advance and sorry about the large amount of code! Albert-Jan From steve at pearwood.info Wed Jan 10 12:54:38 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 11 Jan 2018 04:54:38 +1100 Subject: [Tutor] question about metaclasses In-Reply-To: References: Message-ID: <20180110175438.GS6667@ando.pearwood.info> On Wed, Jan 10, 2018 at 04:08:04PM +0000, Albert-Jan Roskam wrote: > In another thread on this list I was reminded of > types.SimpleNamespace. This is nice, but I wanted to create a bag > class with constants that are read-only. If you expect to specify the names of the constants ahead of time, the best solution is (I think) a namedtuple. from collections import namedtuple Bag = namedtuple('Bag', 'yes no dunno') a = Bag(yes=1, no=0, dunno=42) b = Bag(yes='okay', no='no way', dunno='not a clue') ought to do what you want. Don't make the mistake of doing this: from collections import namedtuple a = namedtuple('Bag', 'yes no dunno')(yes=1, no=0, dunno=42) b = namedtuple('Bag', 'yes no dunno')(yes='okay', no='no way', dunno='not a clue') because that's quite wasteful of memory: each of a and b belong to a separate hidden class, and classes are rather largish objects. If you expect to be able to add new items on the fly, but have them read-only once set, that's a different story. -- Steve From zachary.ware+pytut at gmail.com Wed Jan 10 13:08:39 2018 From: zachary.ware+pytut at gmail.com (Zachary Ware) Date: Wed, 10 Jan 2018 12:08:39 -0600 Subject: [Tutor] question about metaclasses In-Reply-To: References: Message-ID: On Wed, Jan 10, 2018 at 10:08 AM, Albert-Jan Roskam wrote: > Hi, > > > In another thread on this list I was reminded of types.SimpleNamespace. This is nice, but I wanted to create a bag class with constants that are read-only. My main question is about example #3 below (example #2 just illustrates my thought process). Is this a use case to a metaclass? Or can I do it some other way (maybe a class decorator?). I would like to create a metaclass that converts any non-special attributes (=not starting with '_') into properties, if needed. That way I can specify my bag class in a very clean way: I only specify the metaclass, and I list the attributes as normal attrbutes, because the metaclass will convert them into properties. You appear to be reimplementing Enum. > Why does following the line (in #3) not convert the normal attribute into a property? > > setattr(cls, attr, property(lambda self: obj)) # incorrect! Because `cls` is `Meta`, not `MyReadOnlyConst`; `__new__` is implicitly a classmethod and `MyReadOnlyConst` doesn't actually exist yet. When `MyReadOnlyConst` is created by `type.__new__` it will be filled with the contents of `attrs`, so instead of `setattr` you want `attrs[attr] = property(...)`. But once you're past the learning exercise that this is, just use enum.Enum or collections.namedtuple :) -- Zach From __peter__ at web.de Wed Jan 10 13:29:58 2018 From: __peter__ at web.de (Peter Otten) Date: Wed, 10 Jan 2018 19:29:58 +0100 Subject: [Tutor] question about metaclasses References: Message-ID: Albert-Jan Roskam wrote: > Why does following the line (in #3) > # 3------------------------------------------------- > class Meta(type): > def __new__(cls, name, bases, attrs): > for attr, obj in attrs.items(): > if attr.startswith('_'): > continue > elif not isinstance(obj, property): > import pdb;pdb.set_trace() > #setattr(cls, attr, property(lambda self: obj)) # > #incorrect! > raise ValueError("Only properties allowed") > return super().__new__(cls, name, bases, attrs) > > class MyReadOnlyConst(metaclass=Meta): > __metaclass__ = Meta > YES = property(lambda self: 1) > NO = property(lambda self: 0) > DUNNO = property(lambda self: 42) > THROWS_ERROR = 666 > > > c2 = MyReadOnlyConst() > print(c2.THROWS_ERROR) > #c2.THROWS_ERROR = 777 > #print(c2.THROWS_ERROR) > not convert the normal attribute into > a property? > > setattr(cls, attr, property(lambda self: obj)) # incorrect! cls is Meta itself, not MyReadOnlyConst (which is an instance of Meta). When the code in Meta.__new__() executes MyReadOnlyConst does not yet exist, but future attributes are already there, in the form of the attrs dict. Thus to convert the integer value into a read-only property you can manipulate that dict (or the return value of super().__new__()): class Meta(type): def __new__(cls, name, bases, attrs): for attr, obj in attrs.items(): if attr.startswith('_'): continue elif not isinstance(obj, property): attrs[attr] = property(lambda self, obj=obj: obj) return super().__new__(cls, name, bases, attrs) class MyReadOnlyConst(metaclass=Meta): YES = property(lambda self: 1) NO = property(lambda self: 0) DUNNO = property(lambda self: 42) THROWS_ERROR = 666 c = MyReadOnlyConst() try: c.THROWS_ERROR = 42 except AttributeError: pass else: assert False assert c.THROWS_ERROR == 666 PS: If you don't remember why the obj=obj is necessary: Python uses late binding; without that trick all lambda functions would return the value bound to the obj name when the for loop has completed. A simplified example: >>> fs = [lambda: x for x in "abc"] >>> fs[0](), fs[1](), fs[2]() ('c', 'c', 'c') >>> fs = [lambda x=x: x for x in "abc"] >>> fs[0](), fs[1](), fs[2]() ('a', 'b', 'c') From eryksun at gmail.com Wed Jan 10 15:20:57 2018 From: eryksun at gmail.com (eryk sun) Date: Wed, 10 Jan 2018 20:20:57 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> <20180109084733.GG4152@ando.pearwood.info> Message-ID: On Wed, Jan 10, 2018 at 12:59 PM, Albert-Jan Roskam wrote: > > I tried: >>>> from os.path import _getfullpathname >>>> _getfullpathname(r"H:") > 'h:\\path\\to\\folder' >>>> import os >>>> os.getcwd() > 'h:\\path\\to\\folder' > > I expected h:\ to be \\server\share\foo. You called _getfullpathname (WinAPI GetFullPathName), not _getfinalpathname (WinAPI GetFinalPathNameByHandle). GetFullPathName works on the path as a string without touching the filesystem. GetFinalPathNameByHandle reconstructs a path when given a handle to a file or directory. > The fact that the current working directory was returned was even more unexpected. "H:" or "H:relative/path" is relative to the working directory on drive H:. The process only has one working directory, but GetFullPathName also checks for environment variables such as "=H:". The C runtime's _chdir function sets these magic variables, as does Python's os.chdir function (we don't call C _chdir). WinAPI SetCurrentDirectory does not set them. For example: >>> os.chdir('Z:/Temp') >>> win32api.GetEnvironmentVariable('=Z:') 'Z:\\Temp' >>> os.path._getfullpathname('Z:relative') 'Z:\\Temp\\relative' > Why would anybody *want* the drive letters? They are only useful because (a) they save on > keystrokes (b) they bypass the annoying limitation of the cd command on windows, ie. it > does not work with UNC paths. Windows itself has no problem using a UNC path as the working directory. That's a limit of the CMD shell. SUBST drives can be used to access long paths. Since the substitution occurs in the kernel, it avoids the MAX_PATH 260-character limit. Of course, you can also use junctions and symlinks to access long paths, or in Windows 10 simply enable long-path support. > I know net use, pushd, subst. I use 'net use' for more or less permanent drives and > pushd/popd to get a temporary drive, available letter (cd nuisance). `net.exe use` and CMD's PUSHD command (with a UNC path) both call WinAPI WNetAddConnection2 to create a mapped network drive. The difference is that net.exe can supply alternate credentials and create a persistent mapping, while PUSHD uses the current user's credentials and creates a non-persistent mapping. If your account gets logged on with a UAC split token, the standard and elevated tokens actually have separate logon sessions with separate local-device mappings. You can enable a policy to link the two logon sessions. Set a DWORD value of 1 named "EnableLinkedConnections" in the key "HKLM\Software\Microsoft\Windows\CurrentVersion\Policies\System", and reboot. subst.exe creates substitute paths using WinAPI DefineDosDevice. Unlike the WNet API, this function doesn't use MPR (multiple provider router) to create a direct link for the network provider (e.g. \Device\LanmanRedirectory); doesn't create a linked connection when EnableLinkedConnections is defined; and can't create a persistent drive with stored credentials (though you can use an account logon script for this). On the plus side, a drive mapped via subst.exe can target any path. > Interesting code! I have used the following, which uses SHGetFolderPath, ie. without 'Known'. > from win32com.shell import shell, shellcon > desktop = shell.SHGetFolderPath(0, shellcon.CSIDL_DESKTOP, 0, 0) SHGetFolderPath is usually fine, but still, it's outdated and deprecated. win32com.shell doesn't wrap SHGetKnownFolderPath for some reason, but you can still use the new known-folder API without ctypes. Just create a KnownFolderManager instance. For example: import pythoncom from win32com.shell import shell kfmgr = pythoncom.CoCreateInstance(shell.CLSID_KnownFolderManager, None, pythoncom.CLSCTX_INPROC_SERVER, shell.IID_IKnownFolderManager) desktop_path = kfmgr.GetFolder(shell.FOLDERID_Desktop).GetPath() This doesn't work as conveniently for getting known folders of other users. While the high-level SHGetKnownFolderPath function takes care of loading the user profile and impersonating, we have to do this ourselves when using a KnownFolderManager instance. That said, to correct my previous post, you have to be logged on with SeTcbPrivilege access (e.g. a SYSTEM service) to get and set other users' known folders without their password. (If you have the password you can use a regular logon instead of an S4U logon, and that works fine.) > Working with ctypes.wintypes is quite complex! I wouldn't say ctypes is complex in general. But calling LsaLogonUser is complex due to all of the structs that include variable-sized buffers. And working with COM via ctypes is also complex, which is why comtypes exists. From alan.gauld at yahoo.co.uk Wed Jan 10 19:14:15 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 11 Jan 2018 00:14:15 +0000 Subject: [Tutor] Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter? In-Reply-To: References: <20180107080558.GC4152@ando.pearwood.info> <20180109084733.GG4152@ando.pearwood.info> Message-ID: On 10/01/18 20:20, eryk sun wrote: > ... And working with COM via ctypes is also complex, which is why > comtypes exists. Or easier still Pythonwin (aka PyWin32). I far prefer pythonwin over ctypes for any kind of COM 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 cs at cskk.id.au Wed Jan 10 19:40:35 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 11 Jan 2018 11:40:35 +1100 Subject: [Tutor] delete strings from specificed words In-Reply-To: <20180109142008.aduremugxw7ufmby@debian.debian> References: <20180109142008.aduremugxw7ufmby@debian.debian> Message-ID: <20180111004035.GA54986@cskk.homeip.net> On 09Jan2018 22:20, YU Bo wrote: >The text i will working as follow: > >```text [...] >diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c >index a789f952b3e9..443892dabedb 100644 [...] >+++ b/tools/perf/util/util.c [...] >``` >In fact, this is a patch from lkml,my goal is to design a kernel podcast >for myself to focus on what happened in kernel. I have crawled the text >with python and want to remove strings from *diff --git*, because reading >the git commit above, i have a shape in head. > >I have tried split(), replace(), but i have no idea to deal with it. Do you have the text as above - a single string - or coming from a file? I'll presume a single string. I would treat the text as lines, particularly since the diff markers etc are all line oriented. So you might write something like this: interesting = [] for line in the_text.splitlines(): if line.startswith('diff --git '): break interesting.append(line) Now the "interesting" list has the lines you want. There's any number of variations on that you might use, but that should get you going. Cheers, Cameron Simpson From robertvstepp at gmail.com Wed Jan 10 21:02:24 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Wed, 10 Jan 2018 20:02:24 -0600 Subject: [Tutor] When is and isn't "__file__" set? Message-ID: I am actually interested in the answer to this question for Python versions 2.4, 2.6 and 3.x. At https://docs.python.org/3/reference/import.html?highlight=__file__#__file__ it says: __file__ is optional. If set, this attribute?s value must be a string. The import system may opt to leave __file__ unset if it has no semantic meaning (e.g. a module loaded from a database). If __file__ is set, it may also be appropriate to set the __cached__ attribute which is the path to any compiled version of the code (e.g. byte-compiled file). The file does not need to exist to set this attribute; the path can simply point to where the compiled file would exist (see PEP 3147). It is also appropriate to set __cached__ when __file__ is not set. However, that scenario is quite atypical. Ultimately, the loader is what makes use of __file__ and/or __cached__. So if a loader can load from a cached module but otherwise does not load from a file, that atypical scenario may be appropriate. I am still puzzling over things from the thread, "Why does os.path.realpath('test_main.py') give different results for unittest than for testing statement in interpreter?" The basic question I am trying to answer is how to determine the path to a particular module that is being run. For the experiments I have run thus far, the module attribute, "__file__", has so far reliably given me the absolute path to the module being run. But the documentation suggests that this attribute is optional. So what can I rely on here with "__file__"? The first sentence of the cited quote is not illuminating this sufficiently for me. -- boB From steve at pearwood.info Wed Jan 10 21:44:26 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 11 Jan 2018 13:44:26 +1100 Subject: [Tutor] When is and isn't "__file__" set? In-Reply-To: References: Message-ID: <20180111024426.GU6667@ando.pearwood.info> On Wed, Jan 10, 2018 at 08:02:24PM -0600, boB Stepp wrote: > I am still puzzling over things from the thread, "Why does > os.path.realpath('test_main.py') give different results for unittest > than for testing statement in interpreter?" The basic question I am > trying to answer is how to determine the path to a particular module > that is being run. For the experiments I have run thus far, the > module attribute, "__file__", has so far reliably given me the > absolute path to the module being run. But the documentation suggests > that this attribute is optional. So what can I rely on here with > "__file__"? The first sentence of the cited quote is not illuminating > this sufficiently for me. Modules which are loaded from a .py or .pyc file on disk should always have __file__ set. If they don't, that's a bug in the interpreter. Modules which are loaded from a .dll or .so binary file also should have __file__ set. Modules that you create on the fly like this: py> from types import ModuleType py> module = ModuleType('module') py> module.__file__ Traceback (most recent call last): File "", line 1, in AttributeError: module 'module' has no attribute '__file__' will not have __file__ set unless you manually set it yourself. Such hand-made modules can be stored in databases and retrieved later, in which case they still won't have a __file__ attribute. Module objects which are built into the interpreter itself, like sys, also won't have a __file__ attribute: py> sys.__file__ Traceback (most recent call last): File "", line 1, in AttributeError: module 'sys' has no attribute '__file__' One tricky, but unusual case, is that Python supports importing and running modules loaded from zip files. Very few people know this feature even exists -- it is one of Python's best kept secrets -- and even fewer know how it works. I'm not sure what happens when you load a module from a zip file, whether it will have a __file__ or not. Basically, if you still to reading module.__file__ for modules which come from a .py file, you should be absolutely fine. But to practice defensive programming, something like: try: path = module.__file__ except AttributeError: print('handle the case where the module doesn't exist on disk') else: print('handle the case where the module does exist on disk') might be appropriate. -- Steve From tsu.yubo at gmail.com Wed Jan 10 23:16:47 2018 From: tsu.yubo at gmail.com (YU Bo) Date: Thu, 11 Jan 2018 12:16:47 +0800 Subject: [Tutor] delete strings from specificed words In-Reply-To: <20180111004035.GA54986@cskk.homeip.net> References: <20180109142008.aduremugxw7ufmby@debian.debian> <20180111004035.GA54986@cskk.homeip.net> Message-ID: <20180111041645.qion2zqoam4czfnj@debian.debian> Hi, On Thu, Jan 11, 2018 at 11:40:35AM +1100, Cameron Simpson wrote: >On 09Jan2018 22:20, YU Bo wrote: >>The text i will working as follow: >> >>```text >[...] >>diff --git a/tools/perf/util/util.c b/tools/perf/util/util.c >>index a789f952b3e9..443892dabedb 100644 >[...] >>+++ b/tools/perf/util/util.c >[...] >>``` [...] >> >>I have tried split(), replace(), but i have no idea to deal with it. > >Do you have the text as above - a single string - or coming from a >file? I'll presume a single string. En.., the text is multi-string from str(something) within python. > >I would treat the text as lines, particularly since the diff markers >etc are all line oriented. > >So you might write something like this: > > interesting = [] > for line in the_text.splitlines(): > if line.startswith('diff --git '): > break > interesting.append(line) > >Now the "interesting" list has the lines you want. Yes, i test your method and it will come to my intend, but maybe cast a few of other steps. I think that the method will offer a similar ways to solve others issues. I personally like peter's method: text.partition("diff --git")[0].strip() Thanks, Bo > >There's any number of variations on that you might use, but that >should get you going. > >Cheers, >Cameron Simpson From cs at cskk.id.au Thu Jan 11 03:20:42 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 11 Jan 2018 19:20:42 +1100 Subject: [Tutor] delete strings from specificed words In-Reply-To: <20180111041645.qion2zqoam4czfnj@debian.debian> References: <20180111041645.qion2zqoam4czfnj@debian.debian> Message-ID: <20180111082042.GA55776@cskk.homeip.net> On 11Jan2018 12:16, YU Bo wrote: >Hi, Hi, >On Thu, Jan 11, 2018 at 11:40:35AM +1100, Cameron Simpson wrote: >>Do you have the text as above - a single string - or coming from a >>file? I'll presume a single string. > >En.., the text is multi-string from str(something) within python. That's a single string in my thinking. >>I would treat the text as lines, particularly since the diff markers >>etc are all line oriented. >> >>So you might write something like this: >> >>interesting = [] >>for line in the_text.splitlines(): >> if line.startswith('diff --git '): >> break >> interesting.append(line) >> >>Now the "interesting" list has the lines you want. > >Yes, i test your method and it will come to my intend, but maybe cast >a few of other steps. > >I think that the method will offer a similar ways to solve others issues. >I personally like peter's method: text.partition("diff --git")[0].strip() Yes, Peter's partition method is very short and direct. Personally I would include a leading newline in the string, thus: text.partition("\ndiff --git ") to make it more precise. Consider a patch which discusses your script; its comment area might well mention the string "diff --git", as this email does. What you end up with may depend on what further things you do with the text. Cheers, Cameron Simpson From rls4jc at gmail.com Thu Jan 11 17:52:50 2018 From: rls4jc at gmail.com (Roger Lea Scherer) Date: Thu, 11 Jan 2018 14:52:50 -0800 Subject: [Tutor] xlrd has no attribute Message-ID: I'm trying to learn how open a xls file in python. I thought this would be easier. I've read on a blog this code and seen it on other websites. I thought I'd try it out. I'm on Windows 10 with python 3.6.4. import xlrd def open_file(path): """ Open and read an Excel file """ book = xlrd.open_workbook(path) # print number of sheets print(book.nsheets) # print sheet names print(book.sheet_names()) # get the first worksheet first_sheet = book.sheet_by_index(0) # read a row print(first_sheet.row_values(0)) # read a cell cell = first_sheet.cell(0,0) print(cell) print(cell.value) open_file("C:/Users/Roger/Documents/Roger/archive/area codes.xls") But I get an error: Traceback (most recent call last): File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 1, in import xlrd File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 26, in open_file("C:/Users/Roger/Documents/Roger/archive/area codes.xls") File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 7, in open_file book = xlrd.open_workbook(path) AttributeError: module 'xlrd' has no attribute 'open_workbook' I've looked at http://www.lexicon.net/sjmachin/xlrd.html and it looks like it should be ok. I've looked at Stack overflow and I have the opening/closing parentheses appropriately placed to make it a method. Can you help, please? From alan.gauld at yahoo.co.uk Thu Jan 11 19:22:25 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 12 Jan 2018 00:22:25 +0000 Subject: [Tutor] xlrd has no attribute In-Reply-To: References: Message-ID: On 11/01/18 22:52, Roger Lea Scherer wrote: > Traceback (most recent call last): > File "C:\Users\Roger\Documents\Roger\Python\xlrd.py", line 1, in > import xlrd Look closely at the error message. What is the name of the file that causes the error? What is the name of the module you are importing? You are masking the xlrd module with your xlrd.py file and so import your own file. Your file does not have the method so you get an error. Don't name your applications after the modules 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 sjeik_appie at hotmail.com Fri Jan 12 12:22:05 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Fri, 12 Jan 2018 17:22:05 +0000 Subject: [Tutor] When is and isn't "__file__" set? Message-ID: On Jan 11, 2018 03:47, Steven D'Aprano wrote: > > On Wed, Jan 10, 2018 at 08:02:24PM -0600, boB Stepp wrote: > > > I am still puzzling over things from the thread, "Why does > > os.path.realpath('test_main.py') give different results for unittest > > than for testing statement in interpreter?" The basic question I am > > trying to answer is how to determine the path to a particular module > > that is being run. For the experiments I have run thus far, the > > module attribute, "__file__", has so far reliably given me the > > absolute path to the module being run. But the documentation suggests > > that this attribute is optional. So what can I rely on here with > > "__file__"? The first sentence of the cited quote is not illuminating > > this sufficiently for me. > > Modules which are loaded from a .py or .pyc file on disk should always > have __file__ set. If they don't, that's a bug in the interpreter. > > Modules which are loaded from a .dll or .so binary file also should have > __file__ set. And .pyd? I would hope so > Modules that you create on the fly like this: > > py> from types import ModuleType > py> module = ModuleType('module') > py> module.__file__ > Traceback (most recent call last): > File "", line 1, in > AttributeError: module 'module' has no attribute '__file__' Fascinating. Will this allow you to write a BLOB of the marshalled module object to a database? Do you happen to know a use case of this? > will not have __file__ set unless you manually set it yourself. Such > hand-made modules can be stored in databases and retrieved later, in > which case they still won't have a __file__ attribute. > > Module objects which are built into the interpreter itself, like sys, > also won't have a __file__ attribute: > > py> sys.__file__ > Traceback (most recent call last): > File "", line 1, in > AttributeError: module 'sys' has no attribute '__file__' > > > One tricky, but unusual case, is that Python supports importing > and running modules loaded from zip files. Very few people know this > feature even exists -- it is one of Python's best kept secrets -- and > even fewer know how it works. I'm not sure what happens when you load a > module from a zip file, whether it will have a __file__ or not. On this page https://pymotw.com/3/sys/imports.html, I see these lines: "# Set a few properties required by PEP 302 mod.__file__ = fullname " Which suggests to me that it depends on the discipline of the custom importer's author. Since zipimport is part of the standard library, I would *guess* that they follow pep 302. Interesting to test it. > Basically, if you still to reading module.__file__ for modules which > come from a .py file, you should be absolutely fine. But to practice > defensive programming, something like: > > try: > path = module.__file__ > except AttributeError: > print('handle the case where the module doesn't exist on disk') > else: > print('handle the case where the module does exist on disk') > > > might be appropriate. > > > > -- > Steve > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From eryksun at gmail.com Fri Jan 12 18:25:11 2018 From: eryksun at gmail.com (eryk sun) Date: Fri, 12 Jan 2018 23:25:11 +0000 Subject: [Tutor] When is and isn't "__file__" set? In-Reply-To: References: Message-ID: On Fri, Jan 12, 2018 at 5:22 PM, Albert-Jan Roskam wrote: > On Jan 11, 2018 03:47, Steven D'Aprano wrote: >> >> Modules which are loaded from a .dll or .so binary file also should have >> __file__ set. > > And .pyd? I would hope so A .pyd is a Windows DLL (i.e. PE/COFF shared library). The .pyd type is associated with the "Python.Extension" program identifier, which sets a custom descriptive name and icon in Explorer. Sometimes a Python extension module uses the .dll file extension instead of .pyd. For example, from PyWin32: >>> print(pywintypes.__file__) C:\Program Files\Python36\pywintypes36.dll >>> print(pythoncom.__file__) C:\Program Files\Python36\pythoncom36.dll From steve at pearwood.info Fri Jan 12 19:27:47 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 13 Jan 2018 11:27:47 +1100 Subject: [Tutor] When is and isn't "__file__" set? In-Reply-To: References: Message-ID: <20180113002747.GV6667@ando.pearwood.info> On Fri, Jan 12, 2018 at 05:22:05PM +0000, Albert-Jan Roskam wrote: > > On Jan 11, 2018 03:47, Steven D'Aprano wrote: [...] > > Modules which are loaded from a .py or .pyc file on disk should always > > have __file__ set. If they don't, that's a bug in the interpreter. > > > > Modules which are loaded from a .dll or .so binary file also should have > > __file__ set. > > And .pyd? I would hope so The full list of file extensions handled by Python is version and platform dependent. There are also .pyo files, on Windows there is at least one other, .pyw, and there may be more on other platforms. I don't know the full list. > > Modules that you create on the fly like this: > > > > py> from types import ModuleType > > py> module = ModuleType('module') > > py> module.__file__ > > Traceback (most recent call last): > > File "", line 1, in > > AttributeError: module 'module' has no attribute '__file__' > > Fascinating. Will this allow you to write a BLOB of the marshalled > module object to a database? Do you happen to know a use case of this? Apparently you cannot either marshal or pickle a module: py> import pickle, marshal py> from types import ModuleType py> x = ModuleType('x') py> pickle.dumps(x) Traceback (most recent call last): File "", line 1, in _pickle.PicklingError: Can't pickle : attribute lookup module on builtins failed py> marshal.dumps(x) Traceback (most recent call last): File "", line 1, in ValueError: unmarshallable object -- Steve From wpmartin at gmail.com Sat Jan 13 00:15:43 2018 From: wpmartin at gmail.com (Pat Martin) Date: Fri, 12 Jan 2018 21:15:43 -0800 Subject: [Tutor] Graphical/web program Message-ID: Hello, I have recently written a program to add switches and hosts to my ssh config file, I use argparse for some switches like user name and such and it has been working pretty well. I was thinking of turning this into a web app (one that is just run on my local machine) something like have a form with text box, checkbox and radio buttons for the options/flags. My question is, is something like that practical? Will I be able to write to a local file (home/user/.ssh/config) with say a flask app? I don't know flask but am willing to learn it and thought this might be a good program for it. Thanks in advance for any thoughts or ideas. From alan.gauld at yahoo.co.uk Sat Jan 13 04:02:53 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 13 Jan 2018 09:02:53 +0000 Subject: [Tutor] Graphical/web program In-Reply-To: References: Message-ID: On 13/01/18 05:15, Pat Martin wrote: > I was thinking of turning this into a web app (one that is just run on my > local machine) something like have a form with text box, checkbox and > radio buttons for the options/flags. > > My question is, is something like that practical? Will I be able to write > to a local file (home/user/.ssh/config) with say a flask app? I don't know > flask but am willing to learn it and thought this might be a good program > for it. It is definitely doable and as a learning experience on web apps its a good starter project. You will need to run a web server on your machine, but Flask provides a basic server that will suffice. It can write to a file or a database. Looking beyond the web aspect, if its just for your local machine use then a desktop GUI might be a more suitable mechanism than a web page, it would be lighter weight and offer more design features. But if you want to learn Flask then this is a good 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 mamathanaik64 at gmail.com Sat Jan 13 07:05:13 2018 From: mamathanaik64 at gmail.com (mamatha n) Date: Sat, 13 Jan 2018 17:35:13 +0530 Subject: [Tutor] python gui Tkinter Message-ID: please any one give me the code for username (entryfld)----- pwrd (entryfld)---- login(button), changepwrd(button) virtualkeyboard-----user has to be use dis keyboard once click on login button regester page open register page content 1.emply name(entryfld) 2.emply id(entryfld), 3.mbil no(entryfld), 4. RFID(entryfld) , 5.back (button), 6.clearbtn(button), 7. ok(button) next user want to clear employee details click on clear button1. employee id text feild shd open click on ok employee id should be removed please i need this code immediatly any one tell me please. From breamoreboy at gmail.com Sat Jan 13 09:14:34 2018 From: breamoreboy at gmail.com (Mark Lawrence) Date: Sat, 13 Jan 2018 14:14:34 +0000 Subject: [Tutor] python gui Tkinter In-Reply-To: References: Message-ID: On 13/01/18 12:05, mamatha n wrote: > please any one give me the code for > username (entryfld)----- > pwrd (entryfld)---- > login(button), changepwrd(button) > virtualkeyboard-----user has to be use dis keyboard > once click on login button regester page open > register page content 1.emply name(entryfld) > 2.emply id(entryfld), > 3.mbil no(entryfld), 4. RFID(entryfld) , 5.back (button), > 6.clearbtn(button), 7. ok(button) > > next user want to clear employee details click on clear button1. employee > id text feild shd open click on ok employee id should be removed > > please i need this code immediatly any one tell me please. Terribly sorry but that's not how this list works. You provide the code and we help you fix any problems. Anybody giving you the code is doing you a grave disservice in the long term as you will not learn. -- 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 yahoo.co.uk Sat Jan 13 09:18:50 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 13 Jan 2018 14:18:50 +0000 Subject: [Tutor] python gui Tkinter In-Reply-To: References: Message-ID: On 13/01/18 12:05, mamatha n wrote: > please any one give me the code for We don't write code for you (unless you want to pay one of us as a contractor) But we can point you at some examples: > username (entryfld)----- > pwrd (entryfld)---- > login(button), changepwrd(button) So far very basic Tkinter, any tutorial would cover it. You could try mine at: http://www.alan-g.me.uk/tutgui.htm > virtualkeyboard-----user has to be use dis keyboard Thisis not a TKinter function its an OS feature. Tkinter will work with whichever keyboard is present. If you want to create your own vuirtual keyboard using Tkinter then thats possible but quite a lot of work. (More tedious than technically difficult though) > once click on login button regester page open GUIs don't usually have the content of pages - unless you want a tabbed notebook metaphor. If so look at the ttk module But usually I'd expect a pop up dialog box to appear, or for the login window to disappear ad a new main window to appear. You need to clarify how it works. > register page content 1.emply name(entryfld) > 2.emply id(entryfld), > 3.mbil no(entryfld), 4. RFID(entryfld) , 5.back (button), > 6.clearbtn(button), 7. ok(button) Since all you need are entry fields and buttons you should have no problem putting it together with the help of any Tkinter tutorial. You probably want to use the grid layout manager for this. > please i need this code immediatly any one tell me please. You will need to write it, if you get stuck feel free to ask, but its all very basic and covered in any tutorial. -- 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 giacomo.boffi at gmail.com Sat Jan 13 18:35:34 2018 From: giacomo.boffi at gmail.com (giacomo.boffi at gmail.com) Date: Sun, 14 Jan 2018 00:35:34 +0100 Subject: [Tutor] Installing python and numpy on the Mac (OSX) References: <5507B0E1-729B-4D70-AD18-7CAA724204FE@gmail.com> Message-ID: <87zi5h9vsp.fsf@debian.i-did-not-set--mail-host-address--so-tickle-me> Peter Hodges writes: > Hi. I downloaded Python 3.6 from the python site, then followed online > directions for pip to install numpy (in users? ?user was in the > example). > When I start IDLE in the Python 3.6 in Applications and then type > import numpy as np I get the following: > import numpy as np > Traceback (most recent call last): > File "", line 1, in > import numpy as np > ModuleNotFoundError: No module named ?numpy' > > Does this mean I need to set the $PATH with some new pathname? no > Or move the numpy directory into the python 3.6 directory? no > Or? ---- first, (optional but I'd reccommend to) disinstall numpy using the same pip script that you used to install it, something like $ pip uninstall numpy # possibly using sudo ---- next, you must be sure that Python 3.6 has pip, either $ /path/to/python3.6 -m ensurepip --user or (if you are installing in a virtual environment) $ /path/to/python3.6 -m ensurepip the above is going to install pip if it is not already present in the environment of Python 3.6 --- please see https://docs.python.org/3/library/ensurepip.html for the gory details ---- finally, install numpy for 3.6 $ /path/to/python3.6 -m pip install --user numpy ---- The command "/path/to/python3.6 -m modulename ..." ensures that the module and the Python version are matching one with the other. From steve at pearwood.info Sat Jan 13 20:09:00 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 14 Jan 2018 12:09:00 +1100 Subject: [Tutor] question about metaclasses In-Reply-To: References: Message-ID: <20180114010859.GC1982@ando.pearwood.info> On Wed, Jan 10, 2018 at 07:29:58PM +0100, Peter Otten wrote: [...] > elif not isinstance(obj, property): > attrs[attr] = property(lambda self, obj=obj: obj) > PS: If you don't remember why the obj=obj is necessary: > Python uses late binding; without that trick all lambda functions would > return the value bound to the obj name when the for loop has completed. This is true, but I think your terminology is misleading. For default values to function parameters, Python uses *early* binding, not late binding: the default value is computed once at the time the function is created, not each time it is needed. So in this case, each of those property objects use a function that sets the default value of obj to the current value of obj at the time that the property is created. Without the obj=obj parameter, Python creates a *closure*. A closure is a computer-science term for something like a snap shot of the environment where the function was created. If we had written this instead: attrs[attr] = property(lambda self: obj) the name "obj" doesn't refer to a local variable of the lambda function. Nor does it refer to a global variable, or a builtin function. It refers to a "non-local variable": it belongs to the function that surrounds the lambda function, not the lambda itself. And so Python would create a *closure* for the lambda function so that when it eventually gets called, it knows where to find the value of obj. And *that* process, of looking up the value of obj from a closure, uses late binding: all the lambda functions will refer to the same environment, which means they will also see the same value for obj. Namely the last value obj received when the outer function (the one that the closure refers back to) completed. Here's another example to show the difference. Rather than use lambda, I'm going to use regular "def" to prove that this has nothing to do with lambda itself, the rules apply every time you create a function. Start with the closure version: # --- cut here %< --- def factory_closure(): # Create many new functions, each of which refer to i in its # enclosing scope. functions = [] for i in range(5): def f(): return i # << this i is a NONLOCAL variable functions.append(f) return functions functions = factory_closure() # All the closures refer to the same thing. for f in functions: print(f.__closure__) # And the functions all see the same value for i print([f() for f in functions]) # --- cut here %< --- And here is a version which avoids the closure issue by using the function parameter default value trick: # --- cut here %< --- def factory_no_closure(): # Create many new functions, each of which refer to i using # a parameter default value. functions = [] for i in range(5): def f(i=i): return i # << this i is a LOCAL variable functions.append(f) return functions functions = factory_no_closure() # None of the functions need a closure. for g in functions: print(g.__closure__) # And the functions all see different values for i print([g() for g in functions]) # --- cut here %< --- In practice, this is generally only an issue when single invocation of a factory function creates two or more functions at once, and that generally means inside a loop: def factory(): for i in something: create function referring to i If your factory only returns one function at a time, like this: def factory(i): create function referring to i for n in something: factory(n) then each function still uses a closure, but they are *different* closures because each one is created on a different invocation of the factory. That's another way to avoid this "early/late binding" problem. -- Steve From __peter__ at web.de Mon Jan 15 09:40:41 2018 From: __peter__ at web.de (Peter Otten) Date: Mon, 15 Jan 2018 15:40:41 +0100 Subject: [Tutor] question about metaclasses References: <20180114010859.GC1982@ando.pearwood.info> Message-ID: Steven D'Aprano wrote: > On Wed, Jan 10, 2018 at 07:29:58PM +0100, Peter Otten wrote: > > [...] >> elif not isinstance(obj, property): >> attrs[attr] = property(lambda self, obj=obj: obj) > >> PS: If you don't remember why the obj=obj is necessary: >> Python uses late binding; without that trick all lambda functions would >> return the value bound to the obj name when the for loop has completed. > > This is true, but I think your terminology is misleading. For default > values to function parameters, Python uses *early* binding, not late > binding: the default value is computed once at the time the function is > created, not each time it is needed. You are right; I should have stated clearly where I was talking about the closure. From chris_roysmith at internode.on.net Mon Jan 15 23:37:17 2018 From: chris_roysmith at internode.on.net (Chris Roy-Smith) Date: Tue, 16 Jan 2018 15:37:17 +1100 Subject: [Tutor] trouble using tkinter CheckButton Message-ID: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net> Hi, I'm a relative newcomer to object oriented programming. Operating system Linux (ubuntu 17.10) Python version 3.6 With the code below, when I click on the "list set & unset" button I get the following error. This code is my attempt at debugging a bigger program. I have broken things down to what I think is as simple as I can get. Thank you for looking at this, Regards, Chris Roy-Smith Error message: ===================== chris at chris-X451MA:~/Scripts/python3/dvms$ ./debugString.py Exception in Tkinter callback Traceback (most recent call last): ? File "/usr/lib/python3.6/tkinter/__init__.py", line 1702, in __call__ ??? return self.func(*args) ? File "./debugString.py", line 26, in ??? Button(cmember, text='list set & unset',command= lambda lines = x : SetFin(lines) ).grid(row=x, column=2) ? File "./debugString.py", line 7, in SetFin ??? SetStatus[x] = var.get(x) AttributeError: 'list' object has no attribute 'get' ============================================ #!/usr/bin/python3 from tkinter import * def SetFin(lines): ??? SetStatus=[" " for i in range(lines)] ??? for x in range(lines): ??????? SetStatus[x] = var.get(x) ??????? print (SetStatus(x)) master = Tk() NameList=[(1, 'Vivian', 'Blackwell'), (2, 'Peter ', 'Bromell'), (3, 'Nev', 'Casey'), (4, 'Claude', 'Chatwin'), (5, 'John ', 'Dennison'), (6, 'Nicolene', 'Fairbrass'), (7, 'Paul', 'Fairbrass')] #in real situation this comes from a database and is of variable length cmember=Toplevel(master) x=0 y=0 var=[IntVar() for x in range(8)] for line in NameList: ??? for field in line: ??????? Label(cmember, text=field).grid(row=x, column=y) ??????? y+=1 ??? #make checkbox ??? cb=Checkbutton(cmember, text='set', variable=var[x]).grid(row=x, column=y) ??? y=0 ??? x+=1 Button(cmember, text='list set & unset',command= lambda lines = x : SetFin(lines) ).grid(row=x, column=2) Button(cmember, text='exit', command=cmember.destroy).grid(row=x, column=4) mainloop() From alan.gauld at yahoo.co.uk Tue Jan 16 06:35:59 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 16 Jan 2018 11:35:59 +0000 Subject: [Tutor] trouble using tkinter CheckButton In-Reply-To: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net> References: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net> Message-ID: On 16/01/18 04:37, Chris Roy-Smith wrote: > ? File "./debugString.py", line 7, in SetFin > ??? SetStatus[x] = var.get(x) > AttributeError: 'list' object has no attribute 'get' > var=[IntVar() for x in range(8)] Here you create a list of IntVar objects. The list has no get() method - just as the error message says. You need to access the individual IntVar for your widget. I suspect you want SetStatus[x] = var[x].get() -- 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 chris_roysmith at internode.on.net Tue Jan 16 14:47:55 2018 From: chris_roysmith at internode.on.net (Chris Roy-Smith) Date: Wed, 17 Jan 2018 06:47:55 +1100 Subject: [Tutor] trouble using tkinter CheckButton In-Reply-To: References: <1c559cd0-fd41-b10d-aec7-09d6406e0701@internode.on.net> Message-ID: On 16/01/18 22:35, Alan Gauld via Tutor wrote: > On 16/01/18 04:37, Chris Roy-Smith wrote: > >> ? File "./debugString.py", line 7, in SetFin >> ??? SetStatus[x] = var.get(x) >> AttributeError: 'list' object has no attribute 'get' >> var=[IntVar() for x in range(8)] > Here you create a list of IntVar objects. > The list has no get() method - just as the error message says. > You need to access the individual IntVar for your widget. > > I suspect you want > > SetStatus[x] = var[x].get() > Yes, Thank you, that was the problem. other problems in my code, after correcting the get() were easy to sort out. Regards, Chris Roy-Smith From sjeik_appie at hotmail.com Thu Jan 18 12:31:24 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Thu, 18 Jan 2018 17:31:24 +0000 Subject: [Tutor] question about metaclasses Message-ID: On Jan 10, 2018 18:57, Steven D'Aprano wrote: > > On Wed, Jan 10, 2018 at 04:08:04PM +0000, Albert-Jan Roskam wrote: > > > In another thread on this list I was reminded of > > types.SimpleNamespace. This is nice, but I wanted to create a bag > > class with constants that are read-only. > > If you expect to specify the names of the constants ahead of time, the > best solution is (I think) a namedtuple. Aaah *slaps forehead*, for some reason I didn't think about this, though I use namedtuples quite often. Using a metaclass for the very first time was great fun though :-) > from collections import namedtuple > Bag = namedtuple('Bag', 'yes no dunno') > a = Bag(yes=1, no=0, dunno=42) > b = Bag(yes='okay', no='no way', dunno='not a clue') > > ought to do what you want. > > Don't make the mistake of doing this: > > from collections import namedtuple > a = namedtuple('Bag', 'yes no dunno')(yes=1, no=0, dunno=42) > b = namedtuple('Bag', 'yes no dunno')(yes='okay', no='no way', dunno='not a clue') But if I do: Bag = namedtuple('Bag', 'yes no dunno') ... and then I create hundreds of Bag instances, this doesn't have a large memory footprint, right? (Because of __slots__) Or is a regular tuple still (much) less wasteful? > because that's quite wasteful of memory: each of a and b belong to a > separate hidden class, and classes are rather largish objects. > > > If you expect to be able to add new items on the fly, but have them > read-only once set, that's a different story. > > > -- > Steve > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From sjeik_appie at hotmail.com Thu Jan 18 12:14:43 2018 From: sjeik_appie at hotmail.com (Albert-Jan Roskam) Date: Thu, 18 Jan 2018 17:14:43 +0000 Subject: [Tutor] question about metaclasses Message-ID: On Jan 10, 2018 19:32, Peter Otten <__peter__ at web.de> wrote: > > Albert-Jan Roskam wrote: > > > Why does following the line (in #3) > > > # 3------------------------------------------------- > > class Meta(type): > > def __new__(cls, name, bases, attrs): > > for attr, obj in attrs.items(): > > if attr.startswith('_'): > > continue > > elif not isinstance(obj, property): > > import pdb;pdb.set_trace() > > #setattr(cls, attr, property(lambda self: obj)) # > > #incorrect! > > raise ValueError("Only properties allowed") > > return super().__new__(cls, name, bases, attrs) > > > > class MyReadOnlyConst(metaclass=Meta): > > __metaclass__ = Meta > > YES = property(lambda self: 1) > > NO = property(lambda self: 0) > > DUNNO = property(lambda self: 42) > > THROWS_ERROR = 666 > > > > > > c2 = MyReadOnlyConst() > > print(c2.THROWS_ERROR) > > #c2.THROWS_ERROR = 777 > > #print(c2.THROWS_ERROR) > > > not convert the normal attribute int > a property? > > > > setattr(cls, attr, property(lambda self: obj)) # incorrect! > > cls is Meta itself, not MyReadOnlyConst (which is an instance of Meta). > When the code in Meta.__new__() executes MyReadOnlyConst does not yet exist, > but future attributes are already there, in the form of the attrs dict. > Thus to convert the integer value into a read-only property you can > manipulate that dict (or the return value of super().__new__()): > > class Meta(type): > def __new__(cls, name, bases, attrs): > for attr, obj in attrs.items(): > if attr.startswith('_'): > continue > elif not isinstance(obj, property): > attrs[attr] = property(lambda self, obj=obj: obj) > > return super().__new__(cls, name, bases, attrs) > > class MyReadOnlyConst(metaclass=Meta): > YES = property(lambda self: 1) > NO = property(lambda self: 0) > DUNNO = property(lambda self: 42) > THROWS_ERROR = 666 > > c = MyReadOnlyConst() > try: > c.THROWS_ERROR = 42 > except AttributeError: > pass > else: > assert False > assert c.THROWS_ERROR == 666 Thanks all for your replies! Awesome, this is exactly what I want. I think I'll also override __setattr__ so that each newly added attribute is automatically converted into a property Is a metaclass the best/preferred/only way of doing this? Or is a class decorator an alternative route? Is the following analogy for doing stuff when a class is created ('born') correct? Metaclass --> prenatal surgery __new__ --> perinatal surgery Class decorator --> postnatal surgery > PS: If you don't remember why the obj=obj is necessary: > Python uses late binding; without that trick all lambda functions would > return the value bound to the obj name when the for loop has completed. > A simplified example: > > >>> fs = [lambda: x for x in "abc"] > >>> fs[0](), fs[1](), fs[2]() > ('c', 'c', 'c') > >>> fs = [lambda x=x: x for x in "abc"] > >>> fs[0](), fs[1](), fs[2]() > ('a', 'b', 'c') > > > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From devanshr at gmail.com Thu Jan 18 15:51:18 2018 From: devanshr at gmail.com (Devansh Rastogi) Date: Thu, 18 Jan 2018 21:51:18 +0100 Subject: [Tutor] Writing to a file Message-ID: Hello, I'm new to python and programming as such and as an exercise for I/O am writing a small program that reads data from a .txt file, and analyzes the text, ie, number of words/characters, avg. length of words, and frequency of words and characters. Once the text has been analyzed, the results are then written to a file. After reading the documentation, and a bit about json, I'm afraid, I've managed to completely confuse myself. When do you actually use json or pickle, I understand that with data written to .json files can be used by programs written in other languages, and pickle is for python specific objects. So are there specific objects for which .json is used or pickle is preferred? And if I'm just using write() then I'm just writing to a file, and has nothing to do with json or pickle? Also is it possible to append data to a already existing file? So far it seems that everytime I'm calling my write function, its re-writing the whole file with just the last variable called. Ive added my code below, and am currently using json.dump() as I would like to send the file to a friend who is writing a similar program but with a gui, and it would be nice if his program can read the data without problems. I realize these are pretty basic questions and am missing some basic fundamentals. I'd be grateful if someone could point me in the right direction, any tips would be highly appreciated. from collections import Counter import json class Files: def __init__(self, filename): with open(filename, 'r', encoding='utf-16') as file_input: self.file_input_string = file_input.read().replace('\n', ' ') def num_of_words(self): """ Return number of words in the file""" return str(len(self.file_input_string.split())) def num_of_keystrokes(self): """ Total number of keystrokes # abcde.. = 1 stroke # ABCDE.. = 2 strokes # '.,-/;[]=\ = 1 stroke # !@#$%^&*()_+|}{":?>< = 2 strokes """ lowercase_letters = sum(1 for c in self.file_input_string if c.islower()) uppercase_letters = sum(2 for c in self.file_input_string if c.isupper()) one_keystroke_punc = ".,-=[]\;'/ " # space included puncuation_one = sum(1 for c in self.file_input_string if c in one_keystroke_punc) two_keystroke_punc = '!@#$%^&*()_+|}{":?><' puncuation_two = sum(2 for c in self.file_input_string if c in two_keystroke_punc) return str(lowercase_letters + uppercase_letters + puncuation_one + puncuation_two) def num_of_char(self): """ Return number of characters in the string without spaces""" return str(len(self.file_input_string) - self.file_input_string.count(" ")) def frequency_of_char(self): """ Frequency of characters in the file """ count = Counter(self.file_input_string) dict_count = dict(count) print("{:<12} {:<10}".format('Character', 'Frequency')) for k, v in dict_count.items(): print("{:<12} {:<10}".format(k, v)) def frequency_of_words(self): """ Frequency of words in the file""" # word_count = Counter() # for word in self.file_input_string.replace(' ', '\n'): ### macht wider char. sollte fuer line funktioniern # word_count.update(word) # print("{:<15} {:15}".format("Word", "Frequency")) # for k, v in word_count.items(): # print("{:<15} {:<15}".format(k, v)) word_list = self.file_input_string.split() word_frequecy = [word_list.count(w) for w in word_list] ## funktioniert mit string.count!! word_frequecy_dict = dict(zip(word_list, word_frequecy)) print("{:<15} {:15}".format("Word", "Frequency")) for k, v in word_frequecy_dict.items(): print("{:<15} {:<15}".format(k, v)) def average_len_of_words(self): """ calculate the averge length of the words""" word_list = self.file_input_string.split() average = sum(len(word) for word in word_list) / len(word_list) return str(average) def write_to_file(self, data): """ collect all data for Morgen_Kinder.txt in a file""" with open('data.json', 'w') as f: json.dump(data, f, sort_keys=True, indent=4) #test x = Files('Morgen_Kinder.txt') a = Files.num_of_char(x) Files.write_to_file(x,a) print(a) b = Files.num_of_words(x) Files.write_to_file(x,b) print(b) c = Files.frequency_of_char(x) Files.write_to_file(x,c) d = Files.frequency_of_words(x) Files.write_to_file(x,d) e = Files.average_len_of_words(x) Files.write_to_file(x,e) print(e) g = Files.num_of_keystrokes(x) Files.write_to_file(x,g) print(g) From alan.gauld at yahoo.co.uk Thu Jan 18 18:11:05 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Thu, 18 Jan 2018 23:11:05 +0000 Subject: [Tutor] Writing to a file In-Reply-To: References: Message-ID: On 18/01/18 20:51, Devansh Rastogi wrote: > When do you actually use json or pickle, I understand that with data > written to .json files can be used by programs written in other languages, > and pickle is for python specific objects. Yes, that's correct. > So are there specific objects > for which .json is used or pickle is preferred? No, its more about whether you are just looking to persist an objects state (pickle) or share the data with another program(json). > write() then I'm just writing to a file, Correct. write() just send a string to a file. > Also is it possible to append data to a already existing file? Yes open in with mode 'a' instead of 'w' If no file exists it creates a new one, if one exists it appends to the end. > far it seems that everytime I'm calling my write function, its re-writing > the whole file with just the last variable called. Presumably because you open it with 'w' as the mode? > Ive added my code below, and am currently using json.dump() as I would > like to send the file to a friend who is writing a similar program but with > a gui, and it would be nice if his program can read the data without > problems. If the GUI is in Python he can use pickle but otherwise you need json (or some other portable format like csv or xml. > I realize these are pretty basic questions and am missing some basic > fundamentals. I'd be grateful if someone could point me in the right > direction, any tips would be highly appreciated. You could try reading the Handling Files topic in my tutorial http://www.alan-g.me.uk/l2p2/tutfiles.htm > from collections import Counter > import json > > class Files: > def __init__(self, filename): > with open(filename, 'r', encoding='utf-16') as file_input: > self.file_input_string = file_input.read().replace('\n', ' ') Any particular reason you use utf-16 instead of the much more common utf-8? Just curious... > def num_of_words(self): > """ Return number of words in the file""" > return str(len(self.file_input_string.split())) Actually you return the string representation of the number not the actual number. > def num_of_keystrokes(self): > """ Total number of keystrokes > # abcde.. = 1 stroke > # ABCDE.. = 2 strokes > # '.,-/;[]=\ = 1 stroke > # !@#$%^&*()_+|}{":?>< = 2 strokes """ > > lowercase_letters = sum(1 for c in self.file_input_string if > c.islower()) > uppercase_letters = sum(2 for c in self.file_input_string if > c.isupper()) > one_keystroke_punc = ".,-=[]\;'/ " # space included > puncuation_one = sum(1 for c in self.file_input_string if c in > one_keystroke_punc) > two_keystroke_punc = '!@#$%^&*()_+|}{":?><' > puncuation_two = sum(2 for c in self.file_input_string if c in > two_keystroke_punc) > > return str(lowercase_letters + uppercase_letters + > puncuation_one + puncuation_two) Again you are returning the string not the number. > def num_of_char(self): > """ Return number of characters in the string without spaces""" > return str(len(self.file_input_string) - > self.file_input_string.count(" ")) And again... > def frequency_of_char(self): > """ Frequency of characters in the file """ > count = Counter(self.file_input_string) > dict_count = dict(count) > print("{:<12} {:<10}".format('Character', 'Frequency')) > for k, v in dict_count.items(): > print("{:<12} {:<10}".format(k, v)) While this prints the valuers you don;t store them since dict_count is a local variable that gets thrown away. It might be better to store it as a classs attribute? > def frequency_of_words(self): > """ Frequency of words in the file""" > # word_count = Counter() > # for word in self.file_input_string.replace(' ', '\n'): ### > macht wider char. sollte fuer line funktioniern > # word_count.update(word) > # print("{:<15} {:15}".format("Word", "Frequency")) > # for k, v in word_count.items(): > # print("{:<15} {:<15}".format(k, v)) > > word_list = self.file_input_string.split() > word_frequecy = [word_list.count(w) for w in word_list] ## > funktioniert mit string.count!! > word_frequecy_dict = dict(zip(word_list, word_frequecy)) > print("{:<15} {:15}".format("Word", "Frequency")) > for k, v in word_frequecy_dict.items(): > print("{:<15} {:<15}".format(k, v)) > > def average_len_of_words(self): > """ calculate the averge length of the words""" > word_list = self.file_input_string.split() > average = sum(len(word) for word in word_list) / len(word_list) > return str(average) Once again you return the string rather than the value. > def write_to_file(self, data): > """ collect all data for Morgen_Kinder.txt in a file""" > with open('data.json', 'w') as f: > json.dump(data, f, sort_keys=True, indent=4) Here you create the file with 'w' mode so it always overwrites the previous copy. > > #test > x = Files('Morgen_Kinder.txt') > a = Files.num_of_char(x) > Files.write_to_file(x,a) > print(a) > b = Files.num_of_words(x) > Files.write_to_file(x,b) > print(b) Note that here you are writing strings to the files albeit using JSON. But there really is no need for JSON here, the format is simply strings. The pooint of complex formats like pickle and JSON is to save complex data structures all at once. You are getting the worst of both worlds. You are doing all the work to break down the complexity to single strings and then writing them out with the complexity of JSON. -- 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 Thu Jan 18 22:52:08 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Fri, 19 Jan 2018 14:52:08 +1100 Subject: [Tutor] question about metaclasses In-Reply-To: References: Message-ID: <20180119035207.GI22500@ando.pearwood.info> On Thu, Jan 18, 2018 at 05:31:24PM +0000, Albert-Jan Roskam wrote: > > Don't make the mistake of doing this: > > > > from collections import namedtuple > > a = namedtuple('Bag', 'yes no dunno')(yes=1, no=0, dunno=42) > > b = namedtuple('Bag', 'yes no dunno')(yes='okay', no='no way', dunno='not a clue') > > But if I do: > Bag = namedtuple('Bag', 'yes no dunno') > ... and then I create hundreds of Bag instances, this doesn't have a > large memory footprint, right? (Because of __slots__) Or is a regular > tuple still (much) less wasteful? Correct. namedtuple instances are *nearly* as compact as regular tuples. Making many instances of the one named tuple class is efficient; making many named tuple classes, with one instance each, is slow and wasteful of memory. -- Steve From renukeshnk15 at gmail.com Fri Jan 19 01:54:56 2018 From: renukeshnk15 at gmail.com (renukesh nk) Date: Fri, 19 Jan 2018 12:24:56 +0530 Subject: [Tutor] CSV row and column width automation In-Reply-To: References: Message-ID: Hi, Does Web2py framework supports Python version 3.6 ? On Wed, Jan 3, 2018 at 11:01 AM, renukesh nk wrote: > Hi, > > Is there any way to automatically set the column and row width in a CSV > file through python script > > > From bgailer at gmail.com Fri Jan 19 12:58:10 2018 From: bgailer at gmail.com (Bob Gailer) Date: Fri, 19 Jan 2018 12:58:10 -0500 Subject: [Tutor] Writing to a file In-Reply-To: References: Message-ID: = On Jan 18, 2018 5:45 PM, "Devansh Rastogi" wrote: > > Hello, > > I'm new to python and programming as > > from collections import Counter > import json > I don't see any value for having a class. All you need are functions and global variables > class Files: > def __init__(self, filename): I don't see any need for a function or"with". Just write file_input_string = open(filename, 'r', encoding='utf-16').read().replace('\n', ' ') > with open(filename, 'r', encoding='utf-16') as file_input: > self.file_input_string = file_input.read().replace('\n', ' ') > You are assuming that all words are separated by blanks which is rarely the case in natural language. > def num_of_words(self): > """ Return number of words in the file""" > return str(len(self.file_input_string.split())) > Several comments on Counting: Your program is creating lists of ones. Rather than counting them all you need to do is take the length of each list.. e;g;: lowercase_letters = len(1 for c in self.file_input_string if c.islower()) However there is a much better way to do the counting: translate the text using the string translate method into various characters that identify the class of each letter in the file. Then count the occurrences of each of those characters. Example: counting Upper Lower, Nunber, and punctuation Single, Double stroke): txt= "THIS is 123 ,./ :*(" # input file text transtable = str.maketrans("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 ,./:*(", "L"*26 + "U"*26 + "N"*10 + "S"*4 + "D"*3) # maps input characters to corresponding class characters xlation = txt.translate(transtable) # 'UUUUSLLSNNNSSSSSDDD' # creates string of class characters counts =dict(Counter(xlation) # {'S': 7, 'U': 4, 'N': 3, 'L': 2, 'D': 3} > def num_of_keystrokes(self): > """ Total number of keystrokes > # abcde.. = 1 stroke > # ABCDE.. = 2 strokes > # '.,-/;[]=\ = 1 stroke > # !@#$%^&*()_+|}{":?>< = 2 strokes """ > > lowercase_letters = sum(1 for c in self.file_input_string if > c.islower()) > uppercase_letters = sum(2 for c in self.file_input_string if > c.isupper()) > one_keystroke_punc = ".,-=[]\;'/ " # space included > puncuation_one = sum(1 for c in self.file_input_string if c in > one_keystroke_punc) > two_keystroke_punc = '!@#$%^&*()_+|}{":?><' > puncuation_two = sum(2 for c in self.file_input_string if c in > two_keystroke_punc) > > return str(lowercase_letters + uppercase_letters + > puncuation_one + puncuation_two) > > def num_of_char(self): > """ Return number of characters in the string without spaces""" > return str(len(self.file_input_string) - > self.file_input_string.count(" ")) > > def frequency_of_char(self): > """ Frequency of characters in the file """ > count = Counter(self.file_input_string) There is no need to apply dict to count. Counters have an items method. > dict_count = dict(count) > print("{:<12} {:<10}".format('Character', 'Frequency')) > for k, v in dict_count.items(): > print("{:<12} {:<10}".format(k, v)) > > def frequency_of_words(self): > """ Frequency of words in the file""" > # word_count = Counter() > # for word in self.file_input_string.replace(' ', '\n'): ### > macht wider char. sollte fuer line funktioniern > # word_count.update(word) > # print("{:<15} {:15}".format("Word", "Frequency")) > # for k, v in word_count.items(): > # print("{:<15} {:<15}".format(k, v)) > > word_list = self.file_input_string.split() > word_frequecy = [word_list.count(w) for w in word_list] ## > funktioniert mit string.count!! > word_frequecy_dict = dict(zip(word_list, word_frequecy)) > print("{:<15} {:15}".format("Word", "Frequency")) > for k, v in word_frequecy_dict.items(): > print("{:<15} {:<15}".format(k, v)) > > def average_len_of_words(self): > """ calculate the averge length of the words""" > word_list = self.file_input_string.split() > average = sum(len(word) for word in word_list) / len(word_list) > return str(average) > > def write_to_file(self, data): > """ collect all data for Morgen_Kinder.txt in a file""" > with open('data.json', 'w') as f: > json.dump(data, f, sort_keys=True, indent=4) > > #test > x = Files('Morgen_Kinder.txt') > a = Files.num_of_char(x) > Files.write_to_file(x,a) > print(a) > b = Files.num_of_words(x) > Files.write_to_file(x,b) > print(b) > c = Files.frequency_of_char(x) > Files.write_to_file(x,c) > d = Files.frequency_of_words(x) > Files.write_to_file(x,d) > e = Files.average_len_of_words(x) > Files.write_to_file(x,e) > print(e) > g = Files.num_of_keystrokes(x) > Files.write_to_file(x,g) > print(g) > _______________________________________________ > 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 Jan 20 02:09:46 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 20 Jan 2018 18:09:46 +1100 Subject: [Tutor] Writing to a file In-Reply-To: References: Message-ID: <20180120070945.GM22500@ando.pearwood.info> On Fri, Jan 19, 2018 at 12:58:10PM -0500, Bob Gailer wrote: > = > > On Jan 18, 2018 5:45 PM, "Devansh Rastogi" wrote: > > > > Hello, > > > > I'm new to python and programming as > > > > from collections import Counter > > import json > > > I don't see any value for having a class. All you need are functions and > global variables Except for the simplest scripts, global variables are a good way to have fragile, buggy, hard to debug code. If there's ever a chance that you will need to read two or more files at the same time, a class is a much better solution than trying to juggle global variables. If I never have to do the: old_foo = foo calculate_foo() print(foo) foo = old_foo dance again, it won't be too soon. > > class Files: > > def __init__(self, filename): > > I don't see any need for a function or"with". Just write file_input_string > = open(filename, 'r', encoding='utf-16').read().replace('\n', ' ') Again, that doesn't scale beyond quick and dirty scripts. Best practice (even when not strictly needed) is to use with open(filename) as f: do_something_with(f.read()) in order to guarantee that even if an error occurs while reading, the file will be closed. Otherwise, you run the risk of running out of file handles in a long-running program. > > with open(filename, 'r', encoding='utf-16') as file_input: > > self.file_input_string = file_input.read().replace('\n', ' ') > > > You are assuming that all words are separated by blanks which is rarely the > case in natural language. Surelyyoumeanthatitisusuallythecasethatwordsareseparatedbyblanksinmostnaturallanguages? I think that Thai is one of the few exceptions to the rule that most languages separate words with a blank space. In English, there are a small number of compound words that contain spaces (as opposed to the far more common hyphen), such as "ice cream" (neither a form of ice, nor cream) or "attorney general" but most people don't bother distinguishing such compound words and just treating them as a pair of regular words. But I can't think of any English grammatical construct where words are run together while still treating them as separate words (apart from simple mistakes, e.g. accidentally writing "runtogether" as a typo). > Your program is creating lists of ones. Rather than counting them all you > need to do is take the length of each list.. e;g;: lowercase_letters = > len(1 for c in self.file_input_string if c.islower()) That won't work. You are trying to take the length of a generator expression: py> len(1 for c in "abcDe" if c.islower()) Traceback (most recent call last): File "", line 1, in TypeError: object of type 'generator' has no len() > However there is a much better way to do the counting: translate the text > using the string translate method into various characters that identify the > class of each letter in the file. Then count the occurrences of each of > those characters. Example: counting Upper Lower, Nunber, and punctuation > Single, Double stroke): > > txt= "THIS is 123 ,./ :*(" # input file text > > transtable = > str.maketrans("abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789 > ,./:*(", > "L"*26 + "U"*26 + "N"*10 + "S"*4 + "D"*3) # maps input characters to > corresponding class characters That lists only 68 out of the many, many thousands of characters supported by Python. It doesn't scale very well beyond ASCII. -- Steve From DerekSmith at racksquared.com Sat Jan 20 13:26:31 2018 From: DerekSmith at racksquared.com (Derek Smith) Date: Sat, 20 Jan 2018 18:26:31 +0000 Subject: [Tutor] Fwd: print a for loop system call In-Reply-To: References: Message-ID: <17498D60-75A7-4CBE-91F3-A1B3348C644E@racksquared.com> Sent from my iPhone Begin forwarded message: From: Derek Smith > Date: January 19, 2018 at 4:01:58 PM EST To: "tutor-request at python.org" > Subject: print a for loop system call Why does A work but B does not? #!/usr/bin/env python3 import os import sys from subprocess import Popen, PIPE pipe = Popen('lsdev -c tape', shell=True, stdout=PIPE) for dev in pipe.stdout : print ( dev.strip().split()[0].decode() ) ## A ## # print ( dev.strip().split().decode()[0] ) ## B ## And if I try to store in an array using rmts = [ dev.strip().split()[0].decode() ] it only stores the last line when there are over 100 lines. Sample line looks like rmt144 Available 04-T1-01 LTO Ultrium Tape Drive (FCP) thank you! Derek Smith | Unix/TSM Administrator | Racksquared Data Centers ': 614-437-4983 * 325 East Spring Street, Columbus, OH 43215 :: dereksmith at racksquared.com *: www.racksquared.com | www.racksquared.jobs [cid:image003.png at 01D2E9AA.1B9CF8F0] From alan.gauld at yahoo.co.uk Sat Jan 20 18:39:56 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 20 Jan 2018 23:39:56 +0000 Subject: [Tutor] Fwd: print a for loop system call In-Reply-To: <17498D60-75A7-4CBE-91F3-A1B3348C644E@racksquared.com> References: <17498D60-75A7-4CBE-91F3-A1B3348C644E@racksquared.com> Message-ID: On 20/01/18 18:26, Derek Smith wrote: > import os > import sys > from subprocess import Popen, PIPE > > pipe = Popen('lsdev -c tape', shell=True, stdout=PIPE) > > for dev in pipe.stdout : > print ( dev.strip().split()[0].decode() ) ## A ## This is OK > # print ( dev.strip().split().decode()[0] ) ## B ## This tries to decode a list which won't work. split() returns a list. You want to apply decode to a string, specifically the first string that split produces, so it is correct as in option A. If in doubt split the line up and print each component as you create it: for dev in pipe.stdout : print( dev.strip() ) print( dev.strip().split()) print( devb.strip().split()[0]) print( dev.strip().split()[0].decode() ) > And if I try to store in an array using > > rmts = [ dev.strip().split()[0].decode() ] > > it only stores the last line when there are over 100 lines. Wrong, it stores every line as it comes to it. But, since you create a new list each time you throw way the previous one. Only the last list is preserved, but they were all stored, albeit briefly... You need to append() to a list, something like: aList = [] for dev in.... process dev aList.append(result) Or as a list comprehension: aList = [process(dev) for dev 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 steve at pearwood.info Sun Jan 21 05:15:32 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Sun, 21 Jan 2018 21:15:32 +1100 Subject: [Tutor] question about metaclasses In-Reply-To: References: Message-ID: <20180121101531.GP22500@ando.pearwood.info> On Thu, Jan 18, 2018 at 05:14:43PM +0000, Albert-Jan Roskam wrote: > Is a metaclass the best/preferred/only way of doing this? Or is a > class decorator an alternative route? I haven't thought deeply about this, but I suspect a class decorator should do the job too. The general advice is to use the simplest thing that does the job. The deeper you have to go into Python's scary internals, the better reason you should have: - ordinary Python code is simpler than... - code using decorators, which is simpler than... - classes using custom descriptors, which is simpler than... - classes with __init_subclass__, which is simpler than... - code with metaclasses. So in general you should pick the first technique (starting at the top) which solves your problem in a satisfactory manner. The __init_subclass__ method is new to Python 3.6: https://docs.python.org/3/reference/datamodel.html#object.__init_subclass__ Remember the excellent advice: Debugging is harder than programming, so if you write the trickiest and most clever code you are capable of, by definition you won't be able to debug it. Having said that, I applaud you for investigating metaclasses! > Is the following analogy for doing stuff when a class is created ('born') correct? > Metaclass --> prenatal surgery > __new__ --> perinatal surgery > Class decorator --> postnatal surgery The last one is certainly correct: a class decorator gets called with the fully created class object, and then has the opportunity to modify it as needed. It isn't clear to me what you mean by __new__. Do you mean the *class* __new__ method or the *metaclass* __new__ method? If I write this: class MetaC(type): def __new__(meta, *args): # pretend this does something useful class C(metaclass=MetaC): def __new__(cls, *args): ... then MetaC.__new__ and C.__new__ are called at very different times. MetaC.__new__ is called as part of the process of creating C in the first place; so at the beginning of MetaC.__new__, C does not exist. C.__new__ on the other hand doesn't get called when creating C, it gets called when creating instances of C. Think of __new__ as the twin of __init__, with the following differences: * __new__ is called before the instance ("self") exists, and gets to customise the creation of the instance; * __init__ is called after the instance is created, and gets to modify self provided self is mutable. So writing an __init__ method for (say) a string subclass is usually a waste of time, since the string is already set and cannot be changed. This does not work: class UpperString(str): # make strings uppercase def __init__(self): self = self.upper() But this does: class UpperString(str): def __new__(cls, arg): arg = str(arg).upper() return super().__new__(cls, arg) Metaclasses are both extremely powerful *and* mind-blowing (back in Python 1.5, they were known as "the Killer Joke") because they can customise (nearly?) any part of the class operation. So you can think of a metaclass as all of the following: - prenatal surgery (metaclass.__new__); - postnatal surgery (metaclass.__init__); - cybernetic implants (metaclass.__getattribute__, __getattr__ etc); - mind-meld or telepathy between otherwise unrelated classes (define methods in the metaclass as a kind of alternative to inheritence); - gene therapy (all of the above?); - (I can't think of a good analogy for this one): metaclass.__call__ lets you customized what happens when you call your class, allowing you to manipulate the arguments or the returned instance. For example: class Meta(type): def __call__(self, *args): print("called by", self) instance = super().__call__(*args) instance.foo = 1 return instance prints a message and adds a "foo" attribute to every instance of every class that belongs to it. Oh, and just to make it more fun... metaclasses don't have to be a class! See if you can predict what this will do: def meta(*args): print("Hi there, I'm your metaclass for today, how can I blow your mind?") return 42 class A(metaclass=meta): pass See also The Killer Joke: https://www.python.org/doc/essays/metaclasses/ That was written back in Python 1.5 days, so a lot of the information in it is now obsolete. But the basic techniques should more or less work today. -- Steve From alan.gauld at yahoo.co.uk Tue Jan 23 11:25:11 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Tue, 23 Jan 2018 16:25:11 +0000 Subject: [Tutor] Updates to web tutor In-Reply-To: References: Message-ID: On 15/11/17 17:41, Alan Gauld via Tutor wrote: > I've been doing some much needed maintenance to my web tutor. Many thanks for all the feedback received. I know there are at least a couple of minor glitches still to fix - especially on iPhones... However, the rewrite of the material has been done and the presentation stuff seems to be close enough to be usable on any device. As a result I have now launched it as the official V3 version of my tutorial. The front page (link in .sig) has been updated to reflect that, but I plan on major rework there too eventually. Once more, thanks to all who sent comments, and if there are any more I will happily incorporate them in future updates. PS. The old V3 tutor is still there in the background so anyone with bookmarks should not be affected. -- 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 jimmyjconnelly at gmail.com Fri Jan 26 07:31:30 2018 From: jimmyjconnelly at gmail.com (jimmy connelly) Date: Fri, 26 Jan 2018 12:31:30 +0000 Subject: [Tutor] Simple flask app querying twitter keeps crashing. Message-ID: Hello I have a very simple Flask app for fetching tweets from twitter... Its very simple https://twitter-happy-or-sad-b.herokuapp.com/ outputs the word "hello" and nothing else, https://twitter-happy-or-sad-b.herokuapp.com/subject-tweets/any text returns 100 tweets containg 'any text' or 100 tweets containing whatever text you insert as a query string. It runs great for a number of hours then crashes. The / endpoint still outputs hello but the api for fetcing tweets is completly broken after the crash. The app works fine again for a few hours after restarting the dynos manually then it crashes again. I thought maybe it was because the dyno was going to sleep so I upgraded to 'hobby' service., but it doesn't help matters except it seems to run for a little longer before crashing. There is nothing in the logs at the moment because the logs don't go back far enough to the time of the error. I'm really stuck and don't know what to do. Below is the entire code for the app - told you it was simple! import tweepy import json import sys from objdict import ObjDict from flask import Flask from flask import request from vaderSentiment.vaderSentiment import SentimentIntensityAnalyzer from flask_cors import CORS app = Flask(__name__) CORS(app) @app.route("/") def helloWorld(): return "Hello" # Enter authorisations consumer_key = "my-consumer-key" consumer_secret = "my-consumer-secret" access_key = "my-access-key" access_secret = "my-access-secret" # Set up your authorisations auth = tweepy.OAuthHandler(consumer_key, consumer_secret) auth.set_access_token(access_key, access_secret) # Set up API call api = tweepy.API(auth, parser = tweepy.parsers.JSONParser()) #Make another app.route() decorator here that takes in an integer id in the @app.route('/subject-tweets/') def getTweetsofQuery(query): if request.method == 'GET': # Set search query searchquery = query + '-filter:retweets' sentences = [] data = api.search(q = searchquery, count = 100, lang = 'en', result_type = 'mixed') print 'size of data is ' + str(sys.getsizeof(data)) emptyData = False #gotdata = None try: #gotdata = data.values()[1][10]['text'] for x in range(1, 99): sentences.append(data.values()[1][x]['text']) except IndexError: sentences.append('no tweets for ' + query + ' - sorry') emptyData = True except Exception as e: # do something with your exception print(str(e)) # OLD CODE #try: # gotdata = data.values()[1][10]['text'] # for x in range(1, 99): # sentences.append(data.values()[1][x]['text']) #except IndexError: # sentences.append('no tweets for ' + query + ' - sorry') # emptyData = True analyzer = SentimentIntensityAnalyzer() compoundScores = [] for sentence in sentences: vs = analyzer.polarity_scores(sentence) compoundScores.append(vs['compound']) #print(str(vs['compound'])) def mean(compoundScores ): return float(sum(compoundScores )) / max(len(compoundScores ), 1) data = ObjDict() data.subject = query if emptyData == True: data.sentiment = 'sorry we dont have a score for ' + query data.score = "It was impossible to measure sentiment for " + query + " this time because no one tweeted that phrase in the last 7 days" data.tweets = ["Sorry we don't have any tweets for " + query ] else : data.score = mean(compoundScores) data.scoreString = ' The sentiment score for ' + query + ' is ' + str (mean(compoundScores)) if data.score >= 0.5: #data.sentiment = 'The sentiment rating for '+ query + ' is positive' data.sentiment = 'Positive' elif data.score > -0.5 and data.score < 0.5 : #data.sentiment = 'The sentiment rating for '+ query + ' is neutral' data.sentiment = 'Neutral' elif data.score <= -0.5 : #data.sentiment = 'The sentiment rating for '+ query + ' is negative' data.sentiment = 'Negative' data.tweets = sentences json_data = data.dumps() return json.dumps(data) if __name__ == '__main__': app.debug = True app.run(host='0.0.0.0', port=5000) From alan.gauld at yahoo.co.uk Fri Jan 26 07:50:15 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Fri, 26 Jan 2018 12:50:15 +0000 Subject: [Tutor] Simple flask app querying twitter keeps crashing. In-Reply-To: References: Message-ID: On 26/01/18 12:31, jimmy connelly wrote: > Hello I have a very simple Flask app for fetching tweets from twitter... > ... > It runs great for a number of hours then crashes. Caveat, I'm in a hurry and haven't looked at your code. But when things run fine for a long time then crash my first instinct is to think "memory leak". You don't specify OS but if it is *nix like then it probably has vmstat so try running it with, say, a 1 minute delay and log the output to a file. Then see if the memory is being consumed. Or use top or ps whatever other memory monitor you have. Just a thought. -- 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 Fri Jan 26 21:56:31 2018 From: robertvstepp at gmail.com (boB Stepp) Date: Fri, 26 Jan 2018 20:56:31 -0600 Subject: [Tutor] Do _all_ Python builtin methods/functions return "None" IF ... Message-ID: ... they are not designed to explicitly return something else? The reason I ask is that I almost fell into the following trap: py3: a_lst = [0, 1, 2] py3: b_lst = a_lst.append(3) py3: a_lst, b_lst ([0, 1, 2, 3], None) Instead of "None" I was expecting "[0, 1, 2, 3]". Obviously I have a GCE (Gross Conceptual Error). I almost sent the above as my question, but then I realized (Finally!) that lst.append() performs an append operation on lst and returns None. Just like print() returns None. So my actual question is: For these types of methods/functions, is Python Both versions 2 and 3) consistent throughout and *always* returns None? TIA! -- boB From steve at pearwood.info Fri Jan 26 23:32:33 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Sat, 27 Jan 2018 15:32:33 +1100 Subject: [Tutor] Do _all_ Python builtin methods/functions return "None" IF ... In-Reply-To: References: Message-ID: <20180127043233.GF22500@ando.pearwood.info> On Fri, Jan 26, 2018 at 08:56:31PM -0600, boB Stepp wrote: > ... they are not designed to explicitly return something else? Yes. In the absence of an explicit return, all Python functions will return None. > The reason I ask is that I almost fell into the following trap: > > > py3: a_lst = [0, 1, 2] > py3: b_lst = a_lst.append(3) > py3: a_lst, b_lst > ([0, 1, 2, 3], None) > > Instead of "None" I was expecting "[0, 1, 2, 3]". Obviously I have a > GCE (Gross Conceptual Error). > > > I almost sent the above as my question, but then I realized (Finally!) > that lst.append() performs an append operation on lst and returns > None. Just like print() returns None. > > So my actual question is: For these types of methods/functions, is > Python Both versions 2 and 3) consistent throughout and *always* > returns None? Mostly. Python's policy is that functions and methods which operate by side-effect, or modify the object in place (such as list.append, insert, sort, reverse, etc, or dict.update, clear etc), return None. That is to prevent the sort of error where you do this: alist = [4, 1, 2, 5, 3] blist = alist.sort() assert blist == [1, 2, 3, 4, 5] assert alist == [4, 1, 2, 5, 3] # this will fail thinking that list.sort returns a copy. So in general, such functions all return None. However, there have been a few changes, such as file.write method, which used to return None in Python 2 but in Python 3 returns the number of characters actually written. -- Steve From alan.gauld at yahoo.co.uk Sat Jan 27 04:18:38 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sat, 27 Jan 2018 09:18:38 +0000 Subject: [Tutor] Do _all_ Python builtin methods/functions return "None" IF ... In-Reply-To: References: Message-ID: On 27/01/18 02:56, boB Stepp wrote: > So my actual question is: For these types of methods/functions, is > Python Both versions 2 and 3) consistent throughout and *always* > returns None? Mostly, but only for mutable objects. So the string methods return a new string with the modifications because the original string is immutable and cannot be changed. So superficially, list handling methods return none on modification but string methods return the modified string. You need to bear in mind whether the object is mutable or not to understand the expected result. So if you come from SmallTalk, Python is horribly inconsistent. If you come from C then its wonderfully consistent :-) As with all languages you just get used to the foibles. -- 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 cskk.id.au Sat Jan 27 05:54:39 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Sat, 27 Jan 2018 21:54:39 +1100 Subject: [Tutor] Do _all_ Python builtin methods/functions return "None" IF ... In-Reply-To: References: Message-ID: <20180127105439.GA98555@cskk.homeip.net> On 27Jan2018 09:18, Alan Gauld wrote: >On 27/01/18 02:56, boB Stepp wrote: >> So my actual question is: For these types of methods/functions, is >> Python Both versions 2 and 3) consistent throughout and *always* >> returns None? > >Mostly, but only for mutable objects. >So the string methods return a new string with the modifications >because the original string is immutable and cannot be changed. > >So superficially, list handling methods return none on >modification but string methods return the modified string. >You need to bear in mind whether the object is mutable or >not to understand the expected result. For a big more context, the general rule is: if the method fetches a value from the object eg its length, of course it returns something other than None. But if a method _modifies_ the object (append an element to a list, close a file), just affecting its internal state, then the method will usually return None. These modification methods _could_ return a value, but the general practice is not to. Cheers, Cameron Simpson (formerly cs at zip.com.au) From chris_roysmith at internode.on.net Sat Jan 27 21:58:30 2018 From: chris_roysmith at internode.on.net (Chris Roy-Smith) Date: Sun, 28 Jan 2018 13:58:30 +1100 Subject: [Tutor] thinter: can't figure out how to update a window instead of creating a new on Message-ID: <4937c0a6-38b4-25e9-cef0-7cb677529980@internode.on.net> Hi, system: Python 3.6, LInux I have been playing around with the following code which I want to update the window, but I creates a new window (with the correct display), but I have not been able to find the solution. Perhaps I'm using the wrong key words in my searches. Thank you for any assistance, I'm hoping to learn something from this experience Regards, Chris Roy-Smith #!/usr/bin/python3 import mysql.connector from tkinter import * import pickle master = Tk() def getCfg(): ??? fobj = open('members.pkl', 'rb') ??? cfg = pickle.load(fobj) ??? fobj.close() ??? return cfg def editmember(page=1): ??? form=Toplevel(master) ??? form.title('test form') ??? cfg=getCfg() ??? QrySelectMembers='select ident, concat_ws(" " ,`given`, `surname`) as `fullname` from `details` where 1 order by `surname` asc, `given` asc limit '+str(page)+', 10' ??? db=mysql.connector.connect(user = cfg['user'], password = cfg['password'], database = cfg['database']) ??? cursor=db.cursor() ??? cursor.execute(QrySelectMembers) #,(page)) ??? MemberList=list(cursor) ??? cursor.close() ??? db.close ??? ro=0 ??? for Member in MemberList: ??????? ident=Member[0] ??????? msg='edit '+Member[1] ??????? Button(form, text=msg, command= lambda tmp=ident : EdForm(tmp)).grid(sticky=(W, E), row=ro, column=0) ??????? ro+=1 ??? Button(form, text='exit', command=form.destroy).grid(row=ro+1, column=2) ??? Button(form, text='next 10', command= lambda p=page+10 : editmember(p)).grid(row=ro, column=1) ??? Button(form, text="previous 10", command= lambda p=page-10 : editmember(p)).grid(row=ro, column=0) Button(master, text='click to test', command=editmember).grid(row=0, column=0) Button(master, text='quit', command=master.destroy).grid(row=1, column=0) master.mainloop() From alan.gauld at yahoo.co.uk Sun Jan 28 08:01:59 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 28 Jan 2018 13:01:59 +0000 Subject: [Tutor] thinter: can't figure out how to update a window instead of creating a new on In-Reply-To: <4937c0a6-38b4-25e9-cef0-7cb677529980@internode.on.net> References: <4937c0a6-38b4-25e9-cef0-7cb677529980@internode.on.net> Message-ID: On 28/01/18 02:58, Chris Roy-Smith wrote: > I have been playing around with the following code which I want to > update the window, but I creates a new window Yes, you are creating a new window each time. You really need to have a separate unction create the window once and store it (or the widgets of interest) in a variable somewhere. Then your other functions can simply update the widgets through the variable(s) Remember that anything you create inside a function gets thrown away as soon as the function exits. To make it persist you need to move it into global storage (or start using objects, but thats a whole other discussion) -- 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 hancock.g at gmail.com Sun Jan 28 08:36:58 2018 From: hancock.g at gmail.com (Geoff Hancock) Date: Sun, 28 Jan 2018 08:36:58 -0500 Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for a class In-Reply-To: References: Message-ID: Good day- I'm in a difficult situation. I have been asked to help teach students how to clean up a CSV file in Python. The job has fallen to me because the teacher of the course is out on emergency leave and I just found out. Tomorrow I have to show students how to get a CSV file and write code to clean and parse it. I understand the process--BUT I don't know how to do it! What I'm looking for is a simple Step 1 Step 2 Step 3 etc I'm running the latest version of Python and am running on Windows Can anyone assist? Much appreciate the time JGH From leamhall at gmail.com Sun Jan 28 09:20:30 2018 From: leamhall at gmail.com (leam hall) Date: Sun, 28 Jan 2018 09:20:30 -0500 Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for a class In-Reply-To: References: Message-ID: On Sun, Jan 28, 2018 at 8:36 AM, Geoff Hancock wrote: > Good day- > I'm in a difficult situation. > I have been asked to help teach students how to clean up a CSV file in > Python. > The job has fallen to me because the teacher of the course is out on > emergency leave and I just found out. > Tomorrow I have to show students how to get a CSV file and write code to > clean and parse it. > > I understand the process--BUT I don't know how to do it! > What I'm looking for is a simple > Step 1 > Step 2 > Step 3 etc > I'm running the latest version of Python and am running on Windows > Can anyone assist? > > Much appreciate the time > JGH Geoff, I'm not that great a coder but here's where I would start. Assume a file name "gang_draft.csv" that is colon delimited since I'm working on stuff for an RPG session. :) #### file = open('gang_draft.csv', 'r') for line in file: line = line.strip() line_array = line.split(':') print(line_array[1]) #### Where I have print you can do whatever cleanup you like. Then either print specific columns or join them back into a string. Hope that helps start you in the right direction. Others here will likely come up with better solutions. Leam From alan.gauld at yahoo.co.uk Sun Jan 28 09:35:51 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Sun, 28 Jan 2018 14:35:51 +0000 Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for a class In-Reply-To: References: Message-ID: On 28/01/18 13:36, Geoff Hancock wrote: > Good day- > I have been asked to help teach students how to clean up a CSV file in > Python. I'm not sure what you mean by "clean up" a CSV file. If the file is malformed then turning it into a well formed CSV file is a non trivial text processing task. > Tomorrow I have to show students how to get a CSV file and write code to > clean and parse it. Parsing it is easy, and the python.org CSV module documentation includes many examples, so I'd start there. (I'd also show your students that page as a starter too, since learning to go to the documentation is a good thing.) Maybe structure the class around analyzing those examples then trying some of your own? The easiest way to generate a non trivial CSV file is probably to save a spreadsheet from Excel... > I understand the process--BUT I don't know how to do it! > What I'm looking for is a simple > Step 1 > Step 2 > Step 3 etc Umm, I'm not sure what you need here. A CSV file is opened as per a normal file - do you know how to do that? Don't forget to include the DictReader too because it is often better for extracting a sub set of the CSV fields. If you are covering writing CSV files too - although thats less common from Python, you also have the writer and DictWriter classes, and although they do have examples there isn't as much there. Finally a fun thing todo in a classroom environment is to get the students to buddy up and create a CSV file, then pass it to their buddy and get them to decode it. You could also try getting them to read a CSV file the hard way using string handling methods alone, that way the advantages of the CSV tools are more obvious to them! It depends how much time you have. FOr a single study session I'd go with reviewing the CSV module plus a "real world" example. This assumes they even know what a CSV file is. If not, half the lesson could be taken up on the file structure etc before you even get to the code stuff. -- 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 ebroukhim at hotmail.com Sun Jan 28 17:06:05 2018 From: ebroukhim at hotmail.com (Edna Broukhim) Date: Sun, 28 Jan 2018 22:06:05 +0000 Subject: [Tutor] program not doing what I need it to do Message-ID: I have the following program. It needs to say the user's name, average and the letter grade of each user. I don't know how to fix it so it gives the average of all users. It only gives the average of the last user. user=int(input("How many students?")) Score1=[] Score2=[] Score3=[] name=[] for i in range (0, user): name.insert(user, input("What is your name?")) for i in range (0, user): ExamGrades=['exam1','exam2','exam3'] Score1.append(float(input(str(name[i])+ ":What is your score on your first exam?"))) Score2.append(float(input(str(name[i])+ ":What is your score on your second exam?"))) Score3.append(float(input(str(name[i])+ ":What is your score on your third exam?"))) def Average(): global average global grade for i in range (0, user): for j in range(len(Score1)): average=(Score1[j]+ Score2[j]+Score3[j])/3 if(average>=90): grade = "A" elif(average>=80 and average<90): grade="B" elif(average>=70 and average<80): grade="C" elif(average>=60 and average<70): grade="D" else: grade = "F" return average finalAverage=[] for i in range (0, user): finalAverage.append(Average()) print(name[i]+ ":Your average is: "+str(finalAverage[i])+ ", which is " + grade) From alan.gauld at yahoo.co.uk Sun Jan 28 19:45:15 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 29 Jan 2018 00:45:15 +0000 Subject: [Tutor] program not doing what I need it to do In-Reply-To: References: Message-ID: On 28/01/18 22:06, Edna Broukhim wrote: You have tried to give the variables sensible names but a little bit more work will make your code more readable and therefore easier to debug. You need to rethink your data model slightly. You have a number of users (which you don't explicitly store at present). For each user you have 3 exam results. The average is (exam1+exam2+exam3)/3 Instead of storing 3 lists of N results why not store N lists of 3 results? That allows you to leverage Pythons sum() function so your code becomes something like: for user_id in range(num_users): average = sum(scores[user_id])/3 Which I think you will agree is easier to read than the code you currently have? Here are some other general comments: > user=int(input("How many students?")) This is not really the user, it is the number of users so call it something like user_count or num_users or just count. > Score1=[] > Score2=[] > Score3=[] Again these are lists so not single scores, Call them scores1..3 or maybe better still create a list of lists: scores = [] # three sets of scores. > name=[] Again this is not a single name so call it names. > for i in range (0, user): This then becomes: for user_id in range(num_users) > name.insert(user, input("What is your name?")) Here we have a more serious problem. Your name list has no entries so the first inserts will ignore the user_num and just insert the name at the end, so you might as well just use append() instead. insert is really for use in a populated list. The other issue is that while you loop over the numbers up to num_users you always insert at num_users not at i. In fact you ignore i. (or, as I called it, user_id) Instead try for user_id in range(num_users): names.append(input(....)) But why only store the names? Why not add the users scores too? users = [] for user_id in range(num_users): user = [input(....),[]] # empty list for scores users.append(user) > for i in range (0, user): Again this might be clearer as for user_id in range(num_users): > ExamGrades=['exam1','exam2','exam3'] Notice that you assign this every time you go round the loop. You probably only need to do it once before the loop. And again the name is not really reflecting the values. It is not grades but exam names, so the variable should be something like: ExamNames Although by convention we reserve capitalised names for classes so better would be: examNames or exam_names But to be honest I don't think you really need it! > Score1.append(float(input(str(name[i])+ ":What is your score on your first exam?"))) We need to decompose this a bit to see what is happening: prompt = names[user_id] + ":What is your score on exam" + str(exam) value = float(input(prompt)) Score1.append(value) Breaking things into smaller chinks makes it easier to read and you can print the intermediate values if it goes wrong. Putting too much in one line is usually a bad idea. However, with the restructuring I suggested above it could be written as for user in users: print("For user: ",user[0]) # print name as prompt for exam in range(1,4): score = float(input("Score for exam " + str(exam)) user[1].append(score) # add it to the users scores list > def Average(): > global average > global grade Its conventional to initialise global variables outside the function, otherwise they are hard to find when you come to debug another function that uses them. > for i in range (0, user): > for j in range(len(Score1)): > average=(Score1[j]+ Score2[j]+Score3[j])/3 Using my model this becomes: for user in users): average = sum(user[1])/3 > if(average>=90): > grade = "A" > elif(average>=80 and average<90): > grade="B" > elif(average>=70 and average<80): > grade="C" > elif(average>=60 and average<70): > grade="D" > else: > grade = "F" > > return average That bit is OKI although you can tidy it slightly with a Python trick: if(average>=90): grade = "A" elif(80 <= average < 90): grade="B" elif(70 <= average < 80): grade="C" etc > finalAverage=[] > for i in range (0, user): > finalAverage.append(Average()) Rather than create another list why not add the average (and grade?) to each users record within the loop above? user.append( Average() ) You would needto modify the function to return the grade too - otherwise you just throw it away... return (average, grade) # a tuple of ave and grade > print(name[i]+ ":Your average is: "+str(finalAverage[i])+ ", which is " + grade) Since this is outside the loop it only prints the lsat entry... for user in users: print(user[0], "Your average is: ", user[2][0], " and your grade is: " user[2][1] ) I hope that makes sense. The data model you choose has a huge impact on how easy it is to code things. And the names you choose have a big impact on readability. Make lists plural and numbers numbers etc. -- 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 yahoo.co.uk Sun Jan 28 20:37:00 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 29 Jan 2018 01:37:00 +0000 Subject: [Tutor] program not doing what I need it to do In-Reply-To: References: Message-ID: On 29/01/18 00:45, Alan Gauld via Tutor wrote: > scores = [] # three sets of scores. Oops, sorry that line shouldn't be there. It came from my first pass through the code, before I saw how you were storing the data lower down. -- 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 bhaskaran.vinod at gmail.com Mon Jan 29 01:42:57 2018 From: bhaskaran.vinod at gmail.com (vinod bhaskaran) Date: Mon, 29 Jan 2018 12:12:57 +0530 Subject: [Tutor] doubt in a program Message-ID: Hi, I am a new beginner in programming. I saw a code (given below) to reverse string. newstring = '' oldstring = 'Newton' for char in oldstring: newstring = char + newstring print(newstring) Could someone explain how it is traversing to get the string reversed? As the new character is adding the char in the new string but how is it getting reversed without any line giving the char number to be traversed in reverse order. Thanks, Vinod From alan.gauld at yahoo.co.uk Mon Jan 29 04:25:52 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 29 Jan 2018 09:25:52 +0000 Subject: [Tutor] doubt in a program In-Reply-To: References: Message-ID: On 29/01/18 06:42, vinod bhaskaran wrote: > newstring = '' > oldstring = 'Newton' > for char in oldstring: > newstring = char + newstring > print(newstring) > > Could someone explain how it is traversing to get the string reversed? print statements are your friend. Add print statements everywhere that a variable changes value: newstring = '' oldstring = 'Newton' for char in oldstring: print ("char=",char) newstring = char + newstring print(newstring=",newstring) print(newstring) That will let you see how the newstring gets built up inside the loop. You could do the same thing using a paper and pen, just walk through the code in your mind and write down the values each time, like so: char newstring N N e e = N -> eN w w + eN -> weN etc... > As the new character is adding the char in the new string but how is it > getting reversed without any line giving the char number to be traversed in > reverse order. As you will see if you do either of the suggested exercises the addition always puts the latest char at the front of the newstring. -- 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 bhaskaran.vinod at gmail.com Mon Jan 29 04:41:02 2018 From: bhaskaran.vinod at gmail.com (vinod bhaskaran) Date: Mon, 29 Jan 2018 09:41:02 +0000 Subject: [Tutor] doubt in a program In-Reply-To: <4A70D6F1-AE81-4246-B649-CB095AC620C1@g.clemson.edu> References: <4A70D6F1-AE81-4246-B649-CB095AC620C1@g.clemson.edu> Message-ID: Thanks a lot Nitin. I misunderstood the "char + newstring". As a newbie to programming as well as newbie to Python trying to grasp basics. Sure will need the built in functions present for different things in Python. Any suggestion good book for python? Thanks, Vinod Bhaskaran On Mon, Jan 29, 2018, 2:47 PM Nitin Madhok wrote: > Vinod, > > First time it loops, > newstring = ?? > oldstring = ?Newton? > char = ?N? > char + newstring = ?N? + ?? = ?N? > > Second time it loops, > newstring = ?N? > oldstring = ?Newton? > char = ?e? > char + newstring = ?e? +?N? = ?eN? > > Third time it loops, > newstring = ?eN? > oldstring = ?Newton? > char = ?w? > char + newstring = ?w? +?eN? = ?weN? > > Fourth time it loops, > newstring = ?weN? > oldstring = ?Newton? > char = ?t? > char + newstring = ?t? +?weN? = ?tweN? > > Fifth time it loops, > newstring = ?tweN? > oldstring = ?Newton? > char = ?o? > char + newstring = ?o? +?tweN? = ?otweN? > > Sixth/Final time it loops: > newstring = ?otweN? > oldstring = ?Newton? > char = ?n? > char + newstring = ?n? +?otweN? = ?notweN? > > newstring after loop finishes will be ?notweN? which is the reverse of > ?Newton? > > Let me know if that explanation helps you understand it better. There are > built in functions to reverse a string that are more efficient than this > approach that you should be using to reverse a string. > > -- > > Thanks, > Nitin Madhok > Clemson University > > CONFIDENTIALITY NOTICE > This e-mail, and any attachments thereto, is intended only for use by the > addressee(s) named herein and may contain privileged and/or confidential > information. If you are not the intended recipient of this e-mail, any > dissemination, distribution or copying of this e-mail, and any attachments > thereto, is strictly prohibited. If you have received this e-mail in error, > please immediately notify the sender by e-mail or telephone and permanently > delete all copies of this e-mail and any attachments. > > > On Jan 29, 2018, at 1:42 AM, vinod bhaskaran > wrote: > > > > Hi, > > > > I am a new beginner in programming. > > I saw a code (given below) to reverse string. > > > > newstring = '' > > oldstring = 'Newton' > > for char in oldstring: > > newstring = char + newstring > > print(newstring) > > > > > > > > Could someone explain how it is traversing to get the string reversed? > > > > As the new character is adding the char in the new string but how is it > > getting reversed without any line giving the char number to be traversed > in > > reverse order. > > > > Thanks, > > Vinod > > _______________________________________________ > > Tutor maillist - Tutor at python.org > > To unsubscribe or change subscription options: > > https://mail.python.org/mailman/listinfo/tutor > From nmadhok at g.clemson.edu Mon Jan 29 04:17:23 2018 From: nmadhok at g.clemson.edu (Nitin Madhok) Date: Mon, 29 Jan 2018 04:17:23 -0500 Subject: [Tutor] doubt in a program In-Reply-To: References: Message-ID: <4A70D6F1-AE81-4246-B649-CB095AC620C1@g.clemson.edu> Vinod, First time it loops, newstring = ?? oldstring = ?Newton? char = ?N? char + newstring = ?N? + ?? = ?N? Second time it loops, newstring = ?N? oldstring = ?Newton? char = ?e? char + newstring = ?e? +?N? = ?eN? Third time it loops, newstring = ?eN? oldstring = ?Newton? char = ?w? char + newstring = ?w? +?eN? = ?weN? Fourth time it loops, newstring = ?weN? oldstring = ?Newton? char = ?t? char + newstring = ?t? +?weN? = ?tweN? Fifth time it loops, newstring = ?tweN? oldstring = ?Newton? char = ?o? char + newstring = ?o? +?tweN? = ?otweN? Sixth/Final time it loops: newstring = ?otweN? oldstring = ?Newton? char = ?n? char + newstring = ?n? +?otweN? = ?notweN? newstring after loop finishes will be ?notweN? which is the reverse of ?Newton? Let me know if that explanation helps you understand it better. There are built in functions to reverse a string that are more efficient than this approach that you should be using to reverse a string. -- Thanks, Nitin Madhok Clemson University CONFIDENTIALITY NOTICE This e-mail, and any attachments thereto, is intended only for use by the addressee(s) named herein and may contain privileged and/or confidential information. If you are not the intended recipient of this e-mail, any dissemination, distribution or copying of this e-mail, and any attachments thereto, is strictly prohibited. If you have received this e-mail in error, please immediately notify the sender by e-mail or telephone and permanently delete all copies of this e-mail and any attachments. > On Jan 29, 2018, at 1:42 AM, vinod bhaskaran wrote: > > Hi, > > I am a new beginner in programming. > I saw a code (given below) to reverse string. > > newstring = '' > oldstring = 'Newton' > for char in oldstring: > newstring = char + newstring > print(newstring) > > > > Could someone explain how it is traversing to get the string reversed? > > As the new character is adding the char in the new string but how is it > getting reversed without any line giving the char number to be traversed in > reverse order. > > Thanks, > Vinod > _______________________________________________ > Tutor maillist - Tutor at python.org > To unsubscribe or change subscription options: > https://mail.python.org/mailman/listinfo/tutor From lists at mostrom.pp.se Mon Jan 29 08:25:04 2018 From: lists at mostrom.pp.se (Jan Erik =?utf-8?q?Mostr=C3=B6m?=) Date: Mon, 29 Jan 2018 14:25:04 +0100 Subject: [Tutor] doubt in a program In-Reply-To: References: Message-ID: <8EE77C00-BB22-4BE2-BAE9-DF5726E5AA9E@mostrom.pp.se> On 29 Jan 2018, at 7:42, vinod bhaskaran wrote: > As the new character is adding the char in the new string but how is > it > getting reversed without any line giving the char number to be > traversed in > reverse order. You don't need that, think about this example newstring = '' oldstring = "Newton" now you go through each char in oldstring, so you get first N which you add to newstring and you get newstring = 'N' next char is 'e' and then you do 'e' + 'N' and get 'eN' newstring = 'eN' next char the same way newstring = 'weN' etc until you get 'notweN' Remember that the for-loop will step through each char in oldstring so when you come to the end the loop will stop. = jem From neilc at norwich.edu Mon Jan 29 08:48:33 2018 From: neilc at norwich.edu (Neil Cerutti) Date: Mon, 29 Jan 2018 13:48:33 +0000 (UTC) Subject: [Tutor] Fwd: Need help with reading and cleaning CSV files for a class References: Message-ID: On 2018-01-28, Geoff Hancock wrote: > Good day- > I'm in a difficult situation. > I have been asked to help teach students how to clean up a CSV > file in Python. Can you give an example of the kind of thing you need to teach? It is malformed csv that has to be changed into well-formed? That's sounds like a fun and challenging problem. -- Neil Cerutti From sa.testinggeek at gmail.com Mon Jan 29 11:30:12 2018 From: sa.testinggeek at gmail.com (Dragan Mestrovik) Date: Mon, 29 Jan 2018 22:00:12 +0530 Subject: [Tutor] Python GUI Grid like view with checkboxes in first column Message-ID: Hi, I need some suggestions/help in showing large amount of data in grid like view with first column having checkboxes. Please see the image attached. How can i achieve this in Python GUI? [image: Inline image 1]http://oi39.tinypic.com/28vq6wn.jpg From alan.gauld at yahoo.co.uk Mon Jan 29 16:07:38 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Mon, 29 Jan 2018 21:07:38 +0000 Subject: [Tutor] Python GUI Grid like view with checkboxes in first column In-Reply-To: References: Message-ID: On 29/01/18 16:30, Dragan Mestrovik wrote: > I need some suggestions/help in showing large amount of data in grid like > view with first column having checkboxes. Please see the image attached. > How can i achieve this in Python GUI? > [image: Inline image 1]http://oi39.tinypic.com/28vq6wn.jpg The first thing I'd suggest is do not use Tkinter as the GUI. There are other GUI frameworks with a native grid or table control which will be much more suitable. Whether or not they can put a checkbox in the first column is something you will need to investigate. As an example the wxPython framework has a grid component, and it can use custom renderers so I suspect a checkbox would be one such. But for the details I'd ask on the wxPython mailing list. Other frameworks such as GTk and Qt probably have grids 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 joseph.slater at wright.edu Wed Jan 31 08:06:20 2018 From: joseph.slater at wright.edu (Slater, Joseph C.) Date: Wed, 31 Jan 2018 13:06:20 +0000 Subject: [Tutor] python gui Tkinter In-Reply-To: References: Message-ID: <3C930624-5B77-4C96-BFB1-7F2A636EAEB7@wright.edu> > On Jan 13, 2018, at 9:18 AM, Alan Gauld via Tutor wrote: > > On 13/01/18 12:05, mamatha n wrote: >> please any one give me the code for > > We don't write code for you (unless you want to pay > one of us as a contractor) But we can point you at > some examples: > >> username (entryfld)----- >> pwrd (entryfld)---- >> login(button), changepwrd(button) > > So far very basic Tkinter, any tutorial would cover it. > You could try mine at: > > https://urldefense.proofpoint.com/v2/url?u=http-3A__www.alan-2Dg.me.uk_tutgui.htm&d=DwICAg&c=3buyMx9JlH1z22L_G5pM28wz_Ru6WjhVHwo-vpeS0Gk&r=rEyLMZFJ7eh_1iNO7KnqQcXbAnZbNOjKNJqN1v2jbrM&m=TDPz4iOXs_iLt1rddlS505soW8LnHYNnzm_S0Uj51wA&s=gdu771QaCyO11Mgznt3NAgOscLvo5o-1tbFh5mrRPl8&e= > > I found that link failing, but found this instead: http://www.alan-g.me.uk/l2p2/index.htm The l2p2 was missing. Best Regards- Joe From megan.zirger at gmail.com Wed Jan 31 12:42:30 2018 From: megan.zirger at gmail.com (Megan Zirger) Date: Wed, 31 Jan 2018 18:42:30 +0100 Subject: [Tutor] unable to locate python on mac Message-ID: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com> Hi there, I am completely new to python and trying to learn how to set up and get going. The one problem is that I?ve supposedly downloaded the new version. When I run it in the terminal I see that I have the version but I can?t find it anywhere in the applications or anywhere on my computer as to make modifications and be able to work with sublime text. Your help is appreciated. Thank you, Megan From alan.gauld at yahoo.co.uk Wed Jan 31 14:44:07 2018 From: alan.gauld at yahoo.co.uk (Alan Gauld) Date: Wed, 31 Jan 2018 19:44:07 +0000 Subject: [Tutor] unable to locate python on mac In-Reply-To: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com> References: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com> Message-ID: On 31/01/18 17:42, Megan Zirger wrote: > I am completely new to python and trying to learn how to set up and get going. I'm not a Mac expert but v2.7 is usually installed on a Mac by default (although its just a basic version its fine for learning) If you have downloaded v3.6 9the latest version) then it will say so at the banner message that comes up when you run it. AS to where it is located you can find that out at the Terminal OS prompt by typing $ which python3 However you should never need to modify it or do anything to it. > I can?t find it anywhere in the applications You probably won't see it in finder unless you navigate the file system. It is not like a normal GUI style app. > able to work with sublime text. I think that's a text editor right? Or is it more of an IDE? Can you run the code inside sublime? Is that what you are trying to set up? If that's the case you probably need to type in the path to the pyhon3 interpreter in Sublime's settings somewhere. Thats the same path you got from 'which python3' above. If you need more details you will need to ask more specific questions. Bear in mind that although some folks here use Macs most of us don't. -- 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 david at graniteweb.com Wed Jan 31 15:59:18 2018 From: david at graniteweb.com (David Rock) Date: Wed, 31 Jan 2018 14:59:18 -0600 Subject: [Tutor] unable to locate python on mac In-Reply-To: References: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com> Message-ID: > On Jan 31, 2018, at 13:44, Alan Gauld via Tutor wrote: > > If you need more details you will need to ask more specific questions. > Bear in mind that although some folks here use Macs most of us don't. > Another pertinent question is what python did you actually install (i.e., where did you get it from)? Different bundles install differently, so knowing exactly what you downloaded will help identify some of the other questions. ? David Rock david at graniteweb.com From cs at cskk.id.au Wed Jan 31 17:10:05 2018 From: cs at cskk.id.au (Cameron Simpson) Date: Thu, 1 Feb 2018 09:10:05 +1100 Subject: [Tutor] unable to locate python on mac In-Reply-To: References: Message-ID: <20180131221005.GA9239@cskk.homeip.net> On 31Jan2018 19:44, Alan Gauld wrote: >On 31/01/18 17:42, Megan Zirger wrote: >> I am completely new to python and trying to learn how to set up and get >> going. > >I'm not a Mac expert but v2.7 is usually installed on a Mac by default >(although its just a basic version its fine for learning) Yes, the system Python is 2.7: [~]fleet*> /usr/bin/python Python 2.7.10 (default, Oct 23 2015, 19:19:21) [GCC 4.2.1 Compatible Apple LLVM 7.0.0 (clang-700.0.59.5)] on darwin Type "help", "copyright", "credits" or "license" for more information. >>> That's from El Capitan, a few OS releases behind. [...] >> able to work with sublime text. > >I think that's a text editor right? >Or is it more of an IDE? Can you run the code inside sublime? >Is that what you are trying to set up? Subblime Text is just an editor. It's got lots of nice stuff but it isn't an IDE. >If that's the case you probably need to type in the path to the pyhon3 >interpreter in Sublime's settings somewhere. Thats the same path you >got from 'which python3' above. My Sublime text seems to be associated as the default app for opening .py files already. A little surprised here, I use vim mostly and thought I'd bound MacVim (the GUI form of vim on a Mac) for .py files. >If you need more details you will need to ask more specific questions. >Bear in mind that although some folks here use Macs most of us don't. I live on a Mac, I'll watch this thread. But yes, Alan's remark that Python isn't an "app" in the sense of a GUI tool is probably very pertinent. Megan, you may be expecting Python to be a GUI app. It isn't, though it can be used to write them. You also need some sort of arrangement to edit python code and run it. Such arrangements tend to come in 2 basic forms: an IDE (integrated development environment) which is usually a GUI app with both editing and running capabilities, or separate editor and run arrangements. Sublime Text, which I gather you use, is, I thought, just an editor. You also need somewhere to run Python from. Those of use not using IDEs generally run the programmes from a terminal. Personally I use iterm3 for my terminals, lots of nice features. Cheers, Cameron Simpson (formerly cs at zip.com.au) From steve at pearwood.info Wed Jan 31 21:15:40 2018 From: steve at pearwood.info (Steven D'Aprano) Date: Thu, 1 Feb 2018 13:15:40 +1100 Subject: [Tutor] unable to locate python on mac In-Reply-To: References: <9FDB173A-AACF-47D2-B0D4-1267F9990940@gmail.com> Message-ID: <20180201021529.GK26553@ando.pearwood.info> On Wed, Jan 31, 2018 at 07:44:07PM +0000, Alan Gauld via Tutor wrote: > AS to where it is located you can find that out at the Terminal OS > prompt by typing > > $ which python3 You can also run: sys.executable from Python itself. For example, on my system: py> sys.executable '/usr/local/bin/python3.5' It will probably be somewhere different on Mac OS. -- Steve