Show More
@@ -1,3 +1,4 b'' | |||
|
1 | # -*- coding: utf-8 -*- | |
|
1 | 2 | """Implementation of execution-related magic functions. |
|
2 | 3 | """ |
|
3 | 4 | #----------------------------------------------------------------------------- |
@@ -675,7 +676,7 b' python-profiler package from non-free.""")' | |||
|
675 | 676 | del sys.modules[main_mod_name] |
|
676 | 677 | |
|
677 | 678 | return stats |
|
678 | ||
|
679 | ||
|
679 | 680 | @skip_doctest |
|
680 | 681 | @line_cell_magic |
|
681 | 682 | def timeit(self, line='', cell=None): |
@@ -746,31 +747,6 b' python-profiler package from non-free.""")' | |||
|
746 | 747 | those from %timeit.""" |
|
747 | 748 | |
|
748 | 749 | import timeit |
|
749 | import math | |
|
750 | ||
|
751 | # XXX: Unfortunately the unicode 'micro' symbol can cause problems in | |
|
752 | # certain terminals. Until we figure out a robust way of | |
|
753 | # auto-detecting if the terminal can deal with it, use plain 'us' for | |
|
754 | # microseconds. I am really NOT happy about disabling the proper | |
|
755 | # 'micro' prefix, but crashing is worse... If anyone knows what the | |
|
756 | # right solution for this is, I'm all ears... | |
|
757 | # | |
|
758 | # Note: using | |
|
759 | # | |
|
760 | # s = u'\xb5' | |
|
761 | # s.encode(sys.getdefaultencoding()) | |
|
762 | # | |
|
763 | # is not sufficient, as I've seen terminals where that fails but | |
|
764 | # print s | |
|
765 | # | |
|
766 | # succeeds | |
|
767 | # | |
|
768 | # See bug: https://bugs.launchpad.net/ipython/+bug/348466 | |
|
769 | ||
|
770 | #units = [u"s", u"ms",u'\xb5',"ns"] | |
|
771 | units = [u"s", u"ms",u'us',"ns"] | |
|
772 | ||
|
773 | scaling = [1, 1e3, 1e6, 1e9] | |
|
774 | 750 | |
|
775 | 751 | opts, stmt = self.parse_options(line,'n:r:tcp:', |
|
776 | 752 | posix=False, strict=False) |
@@ -855,50 +831,49 b' python-profiler package from non-free.""")' | |||
|
855 | 831 | |
|
856 | 832 | best = min(timer.repeat(repeat, number)) / number |
|
857 | 833 | |
|
858 | if best > 0.0 and best < 1000.0: | |
|
859 | order = min(-int(math.floor(math.log10(best)) // 3), 3) | |
|
860 | elif best >= 1000.0: | |
|
861 | order = 0 | |
|
862 | else: | |
|
863 | order = 3 | |
|
864 | print u"%d loops, best of %d: %.*g %s per loop" % (number, repeat, | |
|
865 | precision, | |
|
866 | best * scaling[order], | |
|
867 | units[order]) | |
|
834 | print u"%d loops, best of %d: %s per loop" % (number, repeat, | |
|
835 | _format_time(best, precision)) | |
|
868 | 836 | if tc > tc_min: |
|
869 | 837 | print "Compiler time: %.2f s" % tc |
|
870 | 838 | |
|
871 | 839 | @skip_doctest |
|
872 | 840 | @needs_local_scope |
|
873 | @line_magic | |
|
874 |
def time(self, |
|
|
841 | @line_cell_magic | |
|
842 | def time(self,line='', cell=None, local_ns=None): | |
|
875 | 843 | """Time execution of a Python statement or expression. |
|
876 | 844 | |
|
877 | 845 | The CPU and wall clock times are printed, and the value of the |
|
878 | 846 | expression (if any) is returned. Note that under Win32, system time |
|
879 | 847 | is always reported as 0, since it can not be measured. |
|
848 | ||
|
849 | This function can be used both as a line and cell magic: | |
|
850 | ||
|
851 | - In line mode you can time a single-line statement (though multiple | |
|
852 | ones can be chained with using semicolons). | |
|
880 | 853 | |
|
881 | This function provides very basic timing functionality. In Python | |
|
882 | 2.3, the timeit module offers more control and sophistication, so this | |
|
883 | could be rewritten to use it (patches welcome). | |
|
854 | - In cell mode, you can time the cell body (a directly | |
|
855 | following statement raises an error). | |
|
856 | ||
|
857 | This function provides very basic timing functionality. Use the timeit | |
|
858 | magic for more controll over the measurement. | |
|
884 | 859 | |
|
885 | 860 | Examples |
|
886 | 861 | -------- |
|
887 | 862 | :: |
|
888 | 863 | |
|
889 | In [1]: time 2**128 | |
|
864 | In [1]: %time 2**128 | |
|
890 | 865 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
891 | 866 | Wall time: 0.00 |
|
892 | 867 | Out[1]: 340282366920938463463374607431768211456L |
|
893 | 868 | |
|
894 | 869 | In [2]: n = 1000000 |
|
895 | 870 | |
|
896 | In [3]: time sum(range(n)) | |
|
871 | In [3]: %time sum(range(n)) | |
|
897 | 872 | CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s |
|
898 | 873 | Wall time: 1.37 |
|
899 | 874 | Out[3]: 499999500000L |
|
900 | 875 | |
|
901 | In [4]: time print 'hello world' | |
|
876 | In [4]: %time print 'hello world' | |
|
902 | 877 | hello world |
|
903 | 878 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
904 | 879 | Wall time: 0.00 |
@@ -909,19 +884,25 b' python-profiler package from non-free.""")' | |||
|
909 | 884 | the expression can take a noticeable amount of time to compute, that |
|
910 | 885 | time is purely due to the compilation: |
|
911 | 886 | |
|
912 | In [5]: time 3**9999; | |
|
887 | In [5]: %time 3**9999; | |
|
913 | 888 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
914 | 889 | Wall time: 0.00 s |
|
915 | 890 | |
|
916 | In [6]: time 3**999999; | |
|
891 | In [6]: %time 3**999999; | |
|
917 | 892 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
918 | 893 | Wall time: 0.00 s |
|
919 | 894 | Compiler : 0.78 s |
|
920 | 895 | """ |
|
921 | 896 | |
|
922 | 897 | # fail immediately if the given expression can't be compiled |
|
923 | ||
|
924 | expr = self.shell.prefilter(parameter_s,False) | |
|
898 | ||
|
899 | if line and cell: | |
|
900 | raise UsageError("Can't use statement directly after '%%time'!") | |
|
901 | ||
|
902 | if cell: | |
|
903 | expr = self.shell.prefilter(cell,False) | |
|
904 | else: | |
|
905 | expr = self.shell.prefilter(line,False) | |
|
925 | 906 | |
|
926 | 907 | # Minimum time above which parse time will be reported |
|
927 | 908 | tp_min = 0.1 |
@@ -967,13 +948,13 b' python-profiler package from non-free.""")' | |||
|
967 | 948 | cpu_user = end[0]-st[0] |
|
968 | 949 | cpu_sys = end[1]-st[1] |
|
969 | 950 | cpu_tot = cpu_user+cpu_sys |
|
970 |
print "CPU times: user % |
|
|
971 | (cpu_user,cpu_sys,cpu_tot) | |
|
972 |
print "Wall time: % |
|
|
951 | print "CPU times: user %s, sys: %s, total: %s" % \ | |
|
952 | (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)) | |
|
953 | print "Wall time: %s" % _format_time(wall_time) | |
|
973 | 954 | if tc > tc_min: |
|
974 |
print "Compiler : % |
|
|
955 | print "Compiler : %s" % _format_time(tc) | |
|
975 | 956 | if tp > tp_min: |
|
976 |
print "Parser : % |
|
|
957 | print "Parser : %s" % _format_time(tp) | |
|
977 | 958 | return out |
|
978 | 959 | |
|
979 | 960 | @skip_doctest |
@@ -1092,3 +1073,44 b' def parse_breakpoint(text, current_file):' | |||
|
1092 | 1073 | return current_file, int(text) |
|
1093 | 1074 | else: |
|
1094 | 1075 | return text[:colon], int(text[colon+1:]) |
|
1076 | ||
|
1077 | def _format_time(timespan, precision=3): | |
|
1078 | """Formats the timespan in a human readable form""" | |
|
1079 | import math | |
|
1080 | ||
|
1081 | if timespan >= 60.0: | |
|
1082 | # we have more than a minute, format that in a human readable form | |
|
1083 | # Idea from http://snipplr.com/view/5713/ | |
|
1084 | parts = [("d", 60*60*24),("h", 60*60),("min", 60), ("s", 1)] | |
|
1085 | time = [] | |
|
1086 | leftover = timespan | |
|
1087 | for suffix, length in parts: | |
|
1088 | value = int(leftover / length) | |
|
1089 | if value > 0: | |
|
1090 | leftover = leftover % length | |
|
1091 | time.append(u'%s%s' % (str(value), suffix)) | |
|
1092 | if leftover < 1: | |
|
1093 | break | |
|
1094 | return " ".join(time) | |
|
1095 | ||
|
1096 | ||
|
1097 | # Unfortunately the unicode 'micro' symbol can cause problems in | |
|
1098 | # certain terminals. | |
|
1099 | # See bug: https://bugs.launchpad.net/ipython/+bug/348466 | |
|
1100 | # Try to prevent crashes by being more secure than it needs to | |
|
1101 | # E.g. eclipse is able to print a µ, but has no sys.stdout.encoding set. | |
|
1102 | units = [u"s", u"ms",u'us',"ns"] # the save value | |
|
1103 | if hasattr(sys.stdout, 'encoding') and sys.stdout.encoding: | |
|
1104 | try: | |
|
1105 | u'\xb5'.encode(sys.stdout.encoding) | |
|
1106 | units = [u"s", u"ms",u'\xb5s',"ns"] | |
|
1107 | except: | |
|
1108 | pass | |
|
1109 | scaling = [1, 1e3, 1e6, 1e9] | |
|
1110 | ||
|
1111 | if timespan > 0.0: | |
|
1112 | order = min(-int(math.floor(math.log10(timespan)) // 3), 3) | |
|
1113 | else: | |
|
1114 | order = 3 | |
|
1115 | ret = u"%.*g %s" % (precision, timespan * scaling[order], units[order]) | |
|
1116 | return ret |
@@ -262,9 +262,6 b' def test_reset_in_length():' | |||
|
262 | 262 | _ip.run_cell("reset -f in") |
|
263 | 263 | nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1) |
|
264 | 264 | |
|
265 | def test_time(): | |
|
266 | _ip.magic('time None') | |
|
267 | ||
|
268 | 265 | def test_tb_syntaxerror(): |
|
269 | 266 | """test %tb after a SyntaxError""" |
|
270 | 267 | ip = get_ipython() |
@@ -286,13 +283,13 b' def test_tb_syntaxerror():' | |||
|
286 | 283 | def test_time(): |
|
287 | 284 | ip = get_ipython() |
|
288 | 285 | |
|
289 |
with tt.AssertPrints("CPU times: user 0 |
|
|
286 | with tt.AssertPrints("CPU times: user 0 ns, sys: 0 ns, total: 0 ns"): | |
|
290 | 287 | ip.run_cell("%time None") |
|
291 | 288 | |
|
292 | 289 | ip.run_cell("def f(kmjy):\n" |
|
293 | 290 | " %time print (2*kmjy)") |
|
294 | 291 | |
|
295 |
with tt.AssertPrints("CPU times: user 0 |
|
|
292 | with tt.AssertPrints("CPU times: user 0 ns, sys: 0 ns, total: 0 ns"): | |
|
296 | 293 | with tt.AssertPrints("hihi", suppress=False): |
|
297 | 294 | ip.run_cell("f('hi')") |
|
298 | 295 |
General Comments 0
You need to be logged in to leave comments.
Login now