Show More
@@ -1,3 +1,4 b'' | |||||
|
1 | # -*- coding: utf-8 -*- | |||
1 | """Implementation of execution-related magic functions. |
|
2 | """Implementation of execution-related magic functions. | |
2 | """ |
|
3 | """ | |
3 | #----------------------------------------------------------------------------- |
|
4 | #----------------------------------------------------------------------------- | |
@@ -675,7 +676,7 b' python-profiler package from non-free.""")' | |||||
675 | del sys.modules[main_mod_name] |
|
676 | del sys.modules[main_mod_name] | |
676 |
|
677 | |||
677 | return stats |
|
678 | return stats | |
678 |
|
679 | |||
679 | @skip_doctest |
|
680 | @skip_doctest | |
680 | @line_cell_magic |
|
681 | @line_cell_magic | |
681 | def timeit(self, line='', cell=None): |
|
682 | def timeit(self, line='', cell=None): | |
@@ -746,31 +747,6 b' python-profiler package from non-free.""")' | |||||
746 | those from %timeit.""" |
|
747 | those from %timeit.""" | |
747 |
|
748 | |||
748 | import timeit |
|
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 | opts, stmt = self.parse_options(line,'n:r:tcp:', |
|
751 | opts, stmt = self.parse_options(line,'n:r:tcp:', | |
776 | posix=False, strict=False) |
|
752 | posix=False, strict=False) | |
@@ -855,50 +831,49 b' python-profiler package from non-free.""")' | |||||
855 |
|
831 | |||
856 | best = min(timer.repeat(repeat, number)) / number |
|
832 | best = min(timer.repeat(repeat, number)) / number | |
857 |
|
833 | |||
858 | if best > 0.0 and best < 1000.0: |
|
834 | print u"%d loops, best of %d: %s per loop" % (number, repeat, | |
859 | order = min(-int(math.floor(math.log10(best)) // 3), 3) |
|
835 | _format_time(best, precision)) | |
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]) |
|
|||
868 | if tc > tc_min: |
|
836 | if tc > tc_min: | |
869 | print "Compiler time: %.2f s" % tc |
|
837 | print "Compiler time: %.2f s" % tc | |
870 |
|
838 | |||
871 | @skip_doctest |
|
839 | @skip_doctest | |
872 | @needs_local_scope |
|
840 | @needs_local_scope | |
873 | @line_magic |
|
841 | @line_cell_magic | |
874 |
def time(self, |
|
842 | def time(self,line='', cell=None, local_ns=None): | |
875 | """Time execution of a Python statement or expression. |
|
843 | """Time execution of a Python statement or expression. | |
876 |
|
844 | |||
877 | The CPU and wall clock times are printed, and the value of the |
|
845 | The CPU and wall clock times are printed, and the value of the | |
878 | expression (if any) is returned. Note that under Win32, system time |
|
846 | expression (if any) is returned. Note that under Win32, system time | |
879 | is always reported as 0, since it can not be measured. |
|
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 |
|
854 | - In cell mode, you can time the cell body (a directly | |
882 | 2.3, the timeit module offers more control and sophistication, so this |
|
855 | following statement raises an error). | |
883 | could be rewritten to use it (patches welcome). |
|
856 | ||
|
857 | This function provides very basic timing functionality. Use the timeit | |||
|
858 | magic for more controll over the measurement. | |||
884 |
|
859 | |||
885 | Examples |
|
860 | Examples | |
886 | -------- |
|
861 | -------- | |
887 | :: |
|
862 | :: | |
888 |
|
863 | |||
889 | In [1]: time 2**128 |
|
864 | In [1]: %time 2**128 | |
890 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
865 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
891 | Wall time: 0.00 |
|
866 | Wall time: 0.00 | |
892 | Out[1]: 340282366920938463463374607431768211456L |
|
867 | Out[1]: 340282366920938463463374607431768211456L | |
893 |
|
868 | |||
894 | In [2]: n = 1000000 |
|
869 | In [2]: n = 1000000 | |
895 |
|
870 | |||
896 | In [3]: time sum(range(n)) |
|
871 | In [3]: %time sum(range(n)) | |
897 | CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s |
|
872 | CPU times: user 1.20 s, sys: 0.05 s, total: 1.25 s | |
898 | Wall time: 1.37 |
|
873 | Wall time: 1.37 | |
899 | Out[3]: 499999500000L |
|
874 | Out[3]: 499999500000L | |
900 |
|
875 | |||
901 | In [4]: time print 'hello world' |
|
876 | In [4]: %time print 'hello world' | |
902 | hello world |
|
877 | hello world | |
903 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
878 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
904 | Wall time: 0.00 |
|
879 | Wall time: 0.00 | |
@@ -909,19 +884,25 b' python-profiler package from non-free.""")' | |||||
909 | the expression can take a noticeable amount of time to compute, that |
|
884 | the expression can take a noticeable amount of time to compute, that | |
910 | time is purely due to the compilation: |
|
885 | time is purely due to the compilation: | |
911 |
|
886 | |||
912 | In [5]: time 3**9999; |
|
887 | In [5]: %time 3**9999; | |
913 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
888 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
914 | Wall time: 0.00 s |
|
889 | Wall time: 0.00 s | |
915 |
|
890 | |||
916 | In [6]: time 3**999999; |
|
891 | In [6]: %time 3**999999; | |
917 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s |
|
892 | CPU times: user 0.00 s, sys: 0.00 s, total: 0.00 s | |
918 | Wall time: 0.00 s |
|
893 | Wall time: 0.00 s | |
919 | Compiler : 0.78 s |
|
894 | Compiler : 0.78 s | |
920 | """ |
|
895 | """ | |
921 |
|
896 | |||
922 | # fail immediately if the given expression can't be compiled |
|
897 | # fail immediately if the given expression can't be compiled | |
923 |
|
898 | |||
924 | expr = self.shell.prefilter(parameter_s,False) |
|
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 | # Minimum time above which parse time will be reported |
|
907 | # Minimum time above which parse time will be reported | |
927 | tp_min = 0.1 |
|
908 | tp_min = 0.1 | |
@@ -967,13 +948,13 b' python-profiler package from non-free.""")' | |||||
967 | cpu_user = end[0]-st[0] |
|
948 | cpu_user = end[0]-st[0] | |
968 | cpu_sys = end[1]-st[1] |
|
949 | cpu_sys = end[1]-st[1] | |
969 | cpu_tot = cpu_user+cpu_sys |
|
950 | cpu_tot = cpu_user+cpu_sys | |
970 |
print "CPU times: user % |
|
951 | print "CPU times: user %s, sys: %s, total: %s" % \ | |
971 | (cpu_user,cpu_sys,cpu_tot) |
|
952 | (_format_time(cpu_user),_format_time(cpu_sys),_format_time(cpu_tot)) | |
972 |
print "Wall time: % |
|
953 | print "Wall time: %s" % _format_time(wall_time) | |
973 | if tc > tc_min: |
|
954 | if tc > tc_min: | |
974 |
print "Compiler : % |
|
955 | print "Compiler : %s" % _format_time(tc) | |
975 | if tp > tp_min: |
|
956 | if tp > tp_min: | |
976 |
print "Parser : % |
|
957 | print "Parser : %s" % _format_time(tp) | |
977 | return out |
|
958 | return out | |
978 |
|
959 | |||
979 | @skip_doctest |
|
960 | @skip_doctest | |
@@ -1092,3 +1073,44 b' def parse_breakpoint(text, current_file):' | |||||
1092 | return current_file, int(text) |
|
1073 | return current_file, int(text) | |
1093 | else: |
|
1074 | else: | |
1094 | return text[:colon], int(text[colon+1:]) |
|
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 | _ip.run_cell("reset -f in") |
|
262 | _ip.run_cell("reset -f in") | |
263 | nt.assert_true(len(_ip.user_ns['In']) == _ip.displayhook.prompt_count+1) |
|
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 | def test_tb_syntaxerror(): |
|
265 | def test_tb_syntaxerror(): | |
269 | """test %tb after a SyntaxError""" |
|
266 | """test %tb after a SyntaxError""" | |
270 | ip = get_ipython() |
|
267 | ip = get_ipython() | |
@@ -286,13 +283,13 b' def test_tb_syntaxerror():' | |||||
286 | def test_time(): |
|
283 | def test_time(): | |
287 | ip = get_ipython() |
|
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 | ip.run_cell("%time None") |
|
287 | ip.run_cell("%time None") | |
291 |
|
288 | |||
292 | ip.run_cell("def f(kmjy):\n" |
|
289 | ip.run_cell("def f(kmjy):\n" | |
293 | " %time print (2*kmjy)") |
|
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 | with tt.AssertPrints("hihi", suppress=False): |
|
293 | with tt.AssertPrints("hihi", suppress=False): | |
297 | ip.run_cell("f('hi')") |
|
294 | ip.run_cell("f('hi')") | |
298 |
|
295 |
General Comments 0
You need to be logged in to leave comments.
Login now