Timer that starts as soon as it is imported
On Fri, May 22, 2015 at 12:59:30PM +0300, anatoly techtonik
Is the idea to have timer that starts on import is good?
No, because: -- it could be imported at the wrong time; -- it couldn't be "reimported"; what is the usage of one-time timer? -- if it could be reset and restarted at need -- why not start it manually in the first place? Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.
On Fri, May 22, 2015 at 1:58 PM, Oleg Broytman
On Fri, May 22, 2015 at 12:59:30PM +0300, anatoly techtonik
wrote: Is the idea to have timer that starts on import is good?
No, because:
-- it could be imported at the wrong time;
Any time is right.
-- it couldn't be "reimported"; what is the usage of one-time timer?
The idea is to have convenient default timer to measure script run-time.
-- if it could be reset and restarted at need -- why not start it manually in the first place?
Current ways of measuring script run-time are not cross-platform or not memorizable. I have to reinvent timer code a couple of times, and that's not convenient for the code that is only relevant while debugging.
On Wed, May 27, 2015 at 4:05 AM, anatoly techtonik
-- if it could be reset and restarted at need -- why not start it manually in the first place?
Current ways of measuring script run-time are not cross-platform or not memorizable. I have to reinvent timer code a couple of times, and that's not convenient for the code that is only relevant while debugging.
Sounds to me like something that doesn't belong in the stdlib, but makes a great utility module for private use. ChrisA
On Tue, May 26, 2015 at 9:21 PM, Chris Angelico
On Wed, May 27, 2015 at 4:05 AM, anatoly techtonik
wrote: -- if it could be reset and restarted at need -- why not start it manually in the first place?
Current ways of measuring script run-time are not cross-platform or not memorizable. I have to reinvent timer code a couple of times, and that's not convenient for the code that is only relevant while debugging.
Sounds to me like something that doesn't belong in the stdlib, but makes a great utility module for private use.
There are a lot of helpers like this that might be useful. Installing them separately is a lot of hassle - it is easy to forget some.
On Wed, May 27, 2015 at 4:24 AM, anatoly techtonik
There are a lot of helpers like this that might be useful. Installing them separately is a lot of hassle - it is easy to forget some.
Package 'em all up into a single repository and clone that repo on every system you use. For me, that's called "shed", and I keep it on github: https://github.com/Rosuav/shed But whether it's public or private, git or hg, pure Python or a mix of languages, it's an easy way to pick up all those convenient little scripts. You'll never "forget some", because they're all in one place. ChrisA
Hi!
On Tue, May 26, 2015 at 09:05:06PM +0300, anatoly techtonik
On Fri, May 22, 2015 at 1:58 PM, Oleg Broytman
wrote: On Fri, May 22, 2015 at 12:59:30PM +0300, anatoly techtonik
wrote: Is the idea to have timer that starts on import is good?
No, because:
-- it could be imported at the wrong time;
Any time is right.
Very much application-dependent. What if you wanna measure import time?
-- it couldn't be "reimported"; what is the usage of one-time timer?
The idea is to have convenient default timer to measure script run-time.
Good idea for a small separate project. Bad for the stdlib. Not every small simple useful module must be in the stdlib. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.
On Tue, May 26, 2015 at 09:24:37PM +0300, anatoly techtonik
On Tue, May 26, 2015 at 9:21 PM, Chris Angelico
wrote: On Wed, May 27, 2015 at 4:05 AM, anatoly techtonik
wrote: -- if it could be reset and restarted at need -- why not start it manually in the first place?
Current ways of measuring script run-time are not cross-platform or not memorizable. I have to reinvent timer code a couple of times, and that's not convenient for the code that is only relevant while debugging.
Sounds to me like something that doesn't belong in the stdlib, but makes a great utility module for private use.
There are a lot of helpers like this that might be useful. Installing them separately is a lot of hassle - it is easy to forget some.
Incorporate them into your main repository as submodules. Oleg. -- Oleg Broytman http://phdru.name/ phd@phdru.name Programmers don't die, they just GOSUB without RETURN.
On Tue, May 26, 2015 at 10:06 PM, Oleg Broytman
On Tue, May 26, 2015 at 09:05:06PM +0300, anatoly techtonik
wrote: On Fri, May 22, 2015 at 1:58 PM, Oleg Broytman
wrote: On Fri, May 22, 2015 at 12:59:30PM +0300, anatoly techtonik
wrote: Is the idea to have timer that starts on import is good?
No, because:
-- it could be imported at the wrong time;
Any time is right.
Very much application-dependent. What if you wanna measure import time?
The design principle is that default behaviour is designed: 1. most simple/intuitive thought 2. most often needed operation Every "what if" means you need to do non-default customization, such as care to place starttimer into your bootstrap script. If you want to trace, when exactly the module is imported, it can record the caller full name sys.path:module.class.method (provided that Python supports this), and lines executed from the Python start.
-- it couldn't be "reimported"; what is the usage of one-time timer?
The idea is to have convenient default timer to measure script run-time.
Good idea for a small separate project. Bad for the stdlib. Not every small simple useful module must be in the stdlib.
Yes. That's not a criteria. The criteria that modules that save time during development should come with bundled. Or another idea - the stdlib should provide a standard layout that people can replicate in their "shed" repositories on Github. Then by crawling these repositories, the names and contents could be aggregated into stats to see what are the most popular imports. That way it will be quickly to identify useful stuff that people coming from other languages find missing in Python. Also, it will allow people to document the behavior differences for modules named the same. -- anatoly t.
On Tue, May 26, 2015 at 9:28 PM, Chris Angelico
On Wed, May 27, 2015 at 4:24 AM, anatoly techtonik
wrote: There are a lot of helpers like this that might be useful. Installing them separately is a lot of hassle - it is easy to forget some.
Package 'em all up into a single repository and clone that repo on every system you use. For me, that's called "shed", and I keep it on github:
https://github.com/Rosuav/shed
But whether it's public or private, git or hg, pure Python or a mix of languages, it's an easy way to pick up all those convenient little scripts. You'll never "forget some", because they're all in one place.
How do you make these importable? Do you git clone it from site-packages? Like: cd site-packages/ git clone .../shed . ??? What if you have two shed repositories with different tools?
On Wed, May 27, 2015 at 6:50 PM, anatoly techtonik
How do you make these importable? Do you git clone it from site-packages? Like:
cd site-packages/ git clone .../shed .
??? What if you have two shed repositories with different tools?
I prefer to operate out of ~ so I'd symlink, but otherwise, yes. And there won't be two sheds, because there is only one me. ChrisA
On Wed, May 27, 2015 at 12:00 PM, Chris Angelico
On Wed, May 27, 2015 at 6:50 PM, anatoly techtonik
wrote: How do you make these importable? Do you git clone it from site-packages? Like:
cd site-packages/ git clone .../shed .
??? What if you have two shed repositories with different tools?
I prefer to operate out of ~ so I'd symlink, but otherwise, yes. And there won't be two sheds, because there is only one me.
symlink every module?
On May 27, 2015, at 02:00, Chris Angelico
On Wed, May 27, 2015 at 6:50 PM, anatoly techtonik
wrote: How do you make these importable? Do you git clone it from site-packages? Like: cd site-packages/ git clone .../shed .
Or just build a trivial distribution out of it and then you can just "pip install git+https://github.com/you/repo".
??? What if you have two shed repositories with different tools?
... which solves that problem.
I prefer to operate out of ~ so I'd symlink, but otherwise, yes. And there won't be two sheds, because there is only one me.
... even if someone figures out how to fork and clone Chris or Anatoly. Anyway, it works for me a lot better than the floppy I used to carry around with abutils.py, .emacs, and half a dozen other files I couldn't live without on a new/borrowed computer.
On Wed, May 27, 2015 at 12:43 PM, Andrew Barnert via Python-ideas
On May 27, 2015, at 02:00, Chris Angelico
wrote: On Wed, May 27, 2015 at 6:50 PM, anatoly techtonik
wrote: How do you make these importable? Do you git clone it from site-packages? Like: cd site-packages/ git clone .../shed .
Or just build a trivial distribution out of it and then you can just "pip install git+https://github.com/you/repo".
But that would make it nested under the "repo" package namespace, no? If not, then how pip detects conflicts when the same file is provided by different sheds? I don't want it to just overwrite my scripts when somebody updates their repository.
??? What if you have two shed repositories with different tools?
... which solves that problem.
I prefer to operate out of ~ so I'd symlink, but otherwise, yes. And there won't be two sheds, because there is only one me.
... even if someone figures out how to fork and clone Chris or Anatoly.
Anyway, it works for me a lot better than the floppy I used to carry around with abutils.py, .emacs, and half a dozen other files I couldn't live without on a new/borrowed computer.
There was no Python in my floppy universe. It probably appeared 10 years later when internet became more accessible and Google said they are hiring. =) I am now more inclined that there needs to be a shed convention to gather statistical data on custom root level importable that may be handy for some kind of "altlib" distribution. -- anatoly t.
On May 27, 2015, at 04:30, anatoly techtonik
On Wed, May 27, 2015 at 12:43 PM, Andrew Barnert via Python-ideas
wrote: On May 27, 2015, at 02:00, Chris Angelico
wrote: On Wed, May 27, 2015 at 6:50 PM, anatoly techtonik
wrote: How do you make these importable? Do you git clone it from site-packages? Like: cd site-packages/ git clone .../shed .
Or just build a trivial distribution out of it and then you can just "pip install git+https://github.com/you/repo".
But that would make it nested under the "repo" package namespace, no?
That depends on how you write your setup.py. It can install a module, a package, three separate packages, whatever you want. I just install one flat module full of helpers (plus a whole bunch of dependencies).
If not, then how pip detects conflicts when the same file is provided by different sheds?
You can't do that. But I don't have a bunch of different sheds in the same environment, and I don't see why you'd want to either. I can imagine having different sheds for different environments (different stuff for base Mac, Linux, and Windows systems, or for venvs targeted to Gtk+ vs. PyObjC vs. Flask web services, or whatever), but I can't imagine wanting to install 7 other people's sheds all at once or something. If someone else's shed were useful enough to me, I'd either merge it into mine, or suggest that they clean it up and put it on PyPI as a real distribution instead of a personal shed (or fork it and do it myself, if they didn't want to maintain it). It's really not much different from using .emacs files (except for the added bonus of being able to pull in dependencies from PyPI and GitHub automatically). I used to look around dotfiles for ideas to borrow from other people's configs, but I never wanted to install 3 .emacs files at the same time.
I don't want it to just overwrite my scripts when somebody updates their repository.
??? What if you have two shed repositories with different tools?
... which solves that problem.
I prefer to operate out of ~ so I'd symlink, but otherwise, yes. And there won't be two sheds, because there is only one me.
... even if someone figures out how to fork and clone Chris or Anatoly.
Anyway, it works for me a lot better than the floppy I used to carry around with abutils.py, .emacs, and half a dozen other files I couldn't live without on a new/borrowed computer.
There was no Python in my floppy universe. It probably appeared 10 years later when internet became more accessible and Google said they are hiring. =)
I am now more inclined that there needs to be a shed convention to gather statistical data on custom root level importable that may be handy for some kind of "altlib" distribution.
I doubt you'd find much of use. There are specialized communities that have a broad set of things usable to most of the community, but those communities already have distributions like Python(x,y) that take care of that. I can't imagine too many things that would be useful to almost everyone. Even obvious things like lxml (and even if you could solve release schedule and similar problems), there are plenty of people with absolutely no need for it, and it has external dependencies like libxml2 that you wouldn't want to force on everyone. Also, I think this thread has shown that, even though the basic shed idea is pretty common among experienced Python devs, different people prefer different variations--whether to pip install or just clone into your venv site-packages, how extensively to make use of git features like submodules or branches, etc. But maybe promoting the idea as a suggestion somewhere in the Python or PyPA docs would get everyone closer to a convention that would make it easier to track. I'm not sure where you'd put it or what you'd say; any ideas?
On Wed, May 27, 2015 at 04:21:01AM +1000, Chris Angelico wrote:
On Wed, May 27, 2015 at 4:05 AM, anatoly techtonik
wrote: -- if it could be reset and restarted at need -- why not start it manually in the first place?
Current ways of measuring script run-time are not cross-platform or not memorizable. I have to reinvent timer code a couple of times, and that's not convenient for the code that is only relevant while debugging.
Sounds to me like something that doesn't belong in the stdlib, but makes a great utility module for private use.
I disagree. I don't think it makes a good utility. I think it is a terrible design, for a number of reasons. (1) Module top level code runs only the first time you import it, after that the module is loaded from cache and the code doesn't run again. So import timer # starts a timer will only start the time the first time you import it. To make it work the second time, you have to do: del sys.modules['timer'] del timer import timer (2) Suppose you find some hack that fixes that problem. Now you have another problem: it's too hard to control when the timer starts. You only have one choice: immediately after the import. So we *have* to write our code like this: import a, b, c # do our regular imports setup = x + y + z # setup everything in advance import timer main() If you move the import timer where the other imports are, as PEP 8 suggests, you'll time too much: all the setup code as well. (3) You can only have one timer at a time. You can't run the timer in two different threads. (At least not with the simplistic UI of "import starts the timer, timer.stop() stops the timer". Contrast that to how timeit works: timeit is an ordinary module that requires no magic to work. Importing it is not the same as running it. You can import it at the top of your code, follow it by setup code, and run the timeit.Timer whenever you like. You can have as many, or as few, timers as you want. The only downside to timeit is that you normally have to provide the timed code as a string. I have a timer context manager which is designed for timing long-running code. You write the code in a "with" block: with Stopwatch(): do_this() do_that() The context manager starts the timer when you enter, and stops it when you leave. By default it prints the time used, but you can easily suppress printing and capture the result instead. I've been using this for a few years now, and it works well. The only downside is that it works too well, so I'm tempted to use it for micro code snippets, so I have it print a warning if the time taken is too small: py> with Stopwatch(): ... n = len("spam") ... elapsed time is very small; consider using timeit.Timer for micro-timings of small code snippets time taken: 0.000010 seconds -- Steve
On May 27, 2015, at 05:18, Steven D'Aprano
On Wed, May 27, 2015 at 04:21:01AM +1000, Chris Angelico wrote: On Wed, May 27, 2015 at 4:05 AM, anatoly techtonik
wrote: -- if it could be reset and restarted at need -- why not start it manually in the first place?
Current ways of measuring script run-time are not cross-platform or not memorizable. I have to reinvent timer code a couple of times, and that's not convenient for the code that is only relevant while debugging.
Sounds to me like something that doesn't belong in the stdlib, but makes a great utility module for private use.
I disagree. I don't think it makes a good utility. I think it is a terrible design, for a number of reasons.
(1) Module top level code runs only the first time you import it, after that the module is loaded from cache and the code doesn't run again. So
import timer # starts a timer
will only start the time the first time you import it. To make it work the second time, you have to do:
del sys.modules['timer'] del timer import timer
(2) Suppose you find some hack that fixes that problem. Now you have another problem: it's too hard to control when the timer starts. You only have one choice: immediately after the import. So we *have* to write our code like this:
import a, b, c # do our regular imports setup = x + y + z # setup everything in advance import timer main()
If you move the import timer where the other imports are, as PEP 8 suggests, you'll time too much: all the setup code as well.
(3) You can only have one timer at a time. You can't run the timer in two different threads. (At least not with the simplistic UI of "import starts the timer, timer.stop() stops the timer".
Presumably you could add a "timer.restart()" to the UI. (But in that case, how much does it really cost to use that at the start of the module instead of the magic import anyway? It's like your system uptime; it's hard to find any use for that besides actually reporting system uptime...)
Contrast that to how timeit works: timeit is an ordinary module that requires no magic to work. Importing it is not the same as running it. You can import it at the top of your code, follow it by setup code, and run the timeit.Timer whenever you like. You can have as many, or as few, timers as you want. The only downside to timeit is that you normally have to provide the timed code as a string.
For many uses, providing it as a function call works just fine, in which case there are no downsides at all.
I have a timer context manager which is designed for timing long-running code. You write the code in a "with" block:
with Stopwatch(): do_this() do_that()
The context manager starts the timer when you enter, and stops it when you leave. By default it prints the time used, but you can easily suppress printing and capture the result instead. I've been using this for a few years now, and it works well. The only downside is that it works too well, so I'm tempted to use it for micro code snippets, so I have it print a warning if the time taken is too small:
py> with Stopwatch(): ... n = len("spam") ... elapsed time is very small; consider using timeit.Timer for micro-timings of small code snippets time taken: 0.000010 seconds
That's a clever idea. I have something very similar, and I sometimes find myself abusing it that way...
On Wed, May 27, 2015 at 5:29 AM, Andrew Barnert via Python-ideas
On May 27, 2015, at 05:18, Steven D'Aprano
wrote: I have a timer context manager which is designed for timing long-running code. You write the code in a "with" block:
with Stopwatch(): do_this() do_that()
The context manager starts the timer when you enter, and stops it when you leave. By default it prints the time used, but you can easily suppress printing and capture the result instead. I've been using this for a few years now, and it works well. The only downside is that it works too well, so I'm tempted to use it for micro code snippets, so I have it print a warning if the time taken is too small:
py> with Stopwatch(): ... n = len("spam") ... elapsed time is very small; consider using timeit.Timer for micro-timings of small code snippets time taken: 0.000010 seconds
That's a clever idea. I have something very similar, and I sometimes find myself abusing it that way...
Why not use an iterable stopwatch that measures time between calls to __next__/next? for _ in Stopwatch(): .... -- Devin
participants (6)
-
anatoly techtonik
-
Andrew Barnert
-
Chris Angelico
-
Devin Jeanpierre
-
Oleg Broytman
-
Steven D'Aprano