Debugging

  • bug

  • de: '반대'를 뜻하는 접두사
  • debugging view in bio
  • debugging view in program

In [1]:
from IPython.display import YouTubeVideo
YouTubeVideo('EWOIf0_tCnk')


Out[1]:

12.1 You will learn

  • What to do when your program does not work
  • How to find and fix typical Python errors
  • How to write programs where errors are easy to find
  • Who to ask for help

12.2 STORY: When your program does not work

12.2.1 Problem Description

  • syntax Errors: 문법 잘못 씀. 컴퓨터가 알아듣게 끔 써라!
  • runtime errors: 실행하는 동안 발생하는 에러
  • logical errors: 이게 가장 찾기 힘듬. 난 맞다고 작성한 코드가 전혀 다른 방식으로 동작할 때. 한줄 한줄 디버깅 해가면서 찾아야 됨

BOX 12.1 ASK FOR HELP

  • An experienced programmer: 어려운 문제를 해결하는 것을 좋아한다.
  • A similarly experienced colleague to whom you can explain the program: 좋은 질문을 해라
  • A nonprogrammer: 네가 무엇을 하는지 간단히 설명하는게 필요하다.
  • Yourself: 피곤하면 쉬어라. 피곤하면 간단한 버그조차 잡을 수 없다.

10.2.2 Example Python Session

오류 버전


In [7]:
def evaluate_data(data, lower=100, upper=300):
    '''Counts data points in three bins.'''
    smaller = 0
    between = 0
    bigger = 0
    
    for length in data:
        if length < lower:
            smaller = smaller + 1
        elif lower < length < upper:
            between = between + 1
        elif length > upper:
            bigger = 1
    return smaller, between, bigger

def read_data(filename):
    '''Reads neuron lengths from a text file.'''
    primary, secondary = [], []
    
    with open(filename) as f:
        for line in f:
            category, length = line.split('\t')
            length = float(length)
            if category == 'Primary':
                primary.append(length)
            elif category == 'Secondary':
                secondary.append(length)
    return primary, secondary

def write_output(filename, count_pri, count_sec):
    '''Writes counted values to a file.'''
    with open(filename, 'w') as output:
        output.write('category <100 100-300 >300\n')
        output.write('Primary : %5i %5i %5i\n' % count_pri)
        output.write('Secondary: %5i %5i %5i\n' % count_sec)
        output.close()
        
primary, secondary = read_data('12-debugging/neuron_data.txt')
count_pri = evaluate_data(primary)
count_sec = evaluate_data(secondary)
write_output('12-debugging/results.txt', count_pri, count_sec)

12.3 What do the commands mean?

a list of error.

  1. SyntaxError: invalid syntax

    File "<ipython-input-9-5b4413ced60a>", line 24
         if category == 'Primary'
                                 ^
     SyntaxError: invalid syntax
    
  2. IOError: [Errno 2] No such file or directory: 'neuron_data1.txt'

    ---------------------------------------------------------------------------
     IOError                                   Traceback (most recent call last)
     <ipython-input-14-f0f285f7761d> in <module>()
          36         output.close()
          37 
     ---> 38 primary, secondary = read_data('12-debugging/neuron_data1.txt')
          39 count_pri = evaluate_data(primary)
          40 count_sec = evaluate_data(secondary)
    
     <ipython-input-14-f0f285f7761d> in read_data(filename)
          18     primary, secondary = [], []
          19 
     ---> 20     with open(filename) as f:
          21         for line in f:
          22             category, length = line.split('\t')
    
     IOError: [Errno 2] No such file or directory: '12-debugging/neuron_data1.txt'
    
  3. NameError: name 'write_output_file' is not defined

    ---------------------------------------------------------------------------
     NameError                                 Traceback (most recent call last)
     <ipython-input-10-e355adcef24f> in <module>()
          39 count_pri = evaluate_data(primary)
          40 count_sec = evaluate_data(secondary)
     ---> 41 write_output_file('12-debugging/results.txt', count_pri, count_sec)
    
     NameError: name 'write_output_file' is not defined
    

12.3.1 Syntax Errors

  • 컴퓨터와 소통하기 위해서는 지켜야 하는 약속
  • python interpretr가 명령어를 해석하지 못해서 에러를 뱉고 멈춤
  • 오타나 잘못된 위치
  • print인데 prin
  • [1,2,3]인데 [1;2;3;]
  • 가장 쉬운 단계라서 쉽게 찾을 수 있다.
  • 이런 기본적인 에러를 방지하기 위해서는 tab키를 자주 사용하여 auto completion 기능을 자주 사용하자.

사람 해석

File "<ipython-input-9-5b4413ced60a>", line 24
    if category == 'Primary'
                            ^( symbole이 위치를 나타낸다.)
SyntaxError: invalid syntax
  • 뭔 귀신 신나락 까먹는 소리냐...

컴퓨터 해석

  • if 다음에는 :이 꼭 와야 되는데 어디다가 버려둔거야? 난 이 문장을 해석할 수 없으니 재주껏 고쳐봐!

BOX 12.2 How to tacke a SYNTAXERROR

  • syntax error message line을 살펴봐
  • if, for, def 문자에는 꼭 :이 문장 마지막에 와야 한다.
  • '''로 시작했으면 종료 위치에도 '''가 있느냐?
  • list, dictionary, tuple 을 사용했을 때 닫는 기호가 있느냐?
  • spaces, tabs가 서로 섞여 있느냐? 섞여 있으면 계속 에러난다.(가장 처음에 접할 때 이 에러가 가장 많은듯. 난 정확히 소스를 짰는데 에러가 났다. 왜 그런가 살펴봤더니 editor 설정은 space이었고, 내가 수정한건 space 여서 그렇다. 서로 섞어 쓰면 안된다. space든 tab이든 하나로 통일하자
  • 에러가 발생한 곳에 라인이나 전체 섹션에 주석을 달아놓자. 만약에 syntax error가 아닌 다른 메세지라면 네 로컬 문제이다.
  • 에러가 발생한 라인이나 섹션을 삭제해 보자. 에러가 없어졌냐?
  • python 2.7 버전으로 작성된 것을 python 3.x 버전으로 실행시킨 것 아니냐? 2.x와 3.x는 문법이 달라졌으니 주의할 것.
  • 2.7은 print 'hi' 이지만 3.x은 print('hi') 이렇게 해야한다.

수정

if category == 'Primary'
if category == 'Primary':

12.3.2 Runtime Errors

  • IOError: [Errno 2] No such file or directory: 'neuron_data1.txt'

---------------------------------------------------------------------------
IOError                                   Traceback (most recent call last)
<ipython-input-14-f0f285f7761d> in <module>()
     36         output.close()
     37 
---> 38 primary, secondary = read_data('12-debugging/neuron_data1.txt')
     39 count_pri = evaluate_data(primary)
     40 count_sec = evaluate_data(secondary)

<ipython-input-14-f0f285f7761d> in read_data(filename)
     18     primary, secondary = [], []
     19 
---> 20     with open(filename) as f:
     21         for line in f:
     22             category, length = line.split('\t')

IOError: [Errno 2] No such file or directory: '12-debugging/neuron_data1.txt'
  • 파이썬이 어떻게 에러 발생한 부분을 정확히 추적해서 보여주나 봤더니 stack 에 쌓는걸 생각하면 쉽게 이해가 된다. 예전 초보때는 굉장히 신기했는데 지금 보니까 당연히 저렇게 stack에 쌓을 수 밖에 없겠구나 싶다.

  • syntax 문제는 없었고 실행할 때 문제가 발생했다.

  • 많은 경우가 여기에 속한다.
  • 변수 할당을 하지 않았거나
  • 파일을 찾지 모한 경우
  • 이 문제를 해결하기 위해서 어떤 일이 발생하는지 분석해야 한다.

  • IOError(Input Output Error): file, program or website 등과 통신할 때 발생,

    • 많은 경우 파일명이나 디렉토리명의 오타에 의해서 발생
    • permission이 없는 경우도 있음
    • 웹페이지 접속은 인터넷 연결이 안되어 있으면 발생
  • 20번째 줄에서 발생
print filename
for line in open(filename):
  • 공백, 대문자, 소문자 주의
  • file 같은 경우 2번 체크(file browser나 terminal 에서 파일이 실제 존재하는지)
  • IOError는 쉽게 고칠 수 있다.

수정

  • neuron_data1.txt -> neuron_data.txt

NameError

---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-15-e355adcef24f> in <module>()
     39 count_pri = evaluate_data(primary)
     40 count_sec = evaluate_data(secondary)
---> 41 write_output_file('12-debugging/results.txt', count_pri, count_sec)

NameError: name 'write_output_file' is not defined
  • 변수 이름, 함수 이름, 다른 object를 알 수 없을 때 발생
  • error가 발생하는 line이 중요하다. 왜냐하면 namespace와 관련되어 있기 때문
  • namespace: 현재 파이썬에서 사용할 수 있는 변수가 저장된 곳
  • 새로운 변수나 함수로 들어갔다가 돌아올 때 새로운 함수의 위치에 있는 변수를 참조하려면 NameError 발생
  • A name was not imported
    • import name
  • A variable has not been initialized
    • counter = counter + 1을 하기 위해서는
    • counter = 0 이 먼저 선행되어야 함
    • if a > 5:
        counter = 0
      counter = counter + 1
      
      • 이렇게 변수를 할당하게 되면 a가 6보다 크게 되면 counter 변수가 초기화되지 않는다. 그러므로 변수를 할당할 때는 꼭 condition 이 없이 할당하라.
  • A variable or function name is misspelled
    • write_output_file 같이 오타 발생
    • write_output 이 정확함

NameError를 분석할 수 있는 쉬운 방법은

print dir()
  • 을 하게 되면 현재 사용할 수 있는 변수들을 쉽게 알 수 있다.

In [17]:
help(dir)


Help on built-in function dir in module __builtin__:

dir(...)
    dir([object]) -> list of strings
    
    If called without an argument, return the names in the current scope.
    Else, return an alphabetized list of names comprising (some of) the attributes
    of the given object, and of attributes reachable from it.
    If the object supplies a method named __dir__, it will be used; otherwise
    the default dir() logic is used and returns:
      for a module object: the module's attributes.
      for a class object:  its attributes, and recursively the attributes
        of its bases.
      for any other object: its attributes, its class's attributes, and
        recursively the attributes of its class's base classes.


In [16]:
print dir()


['ALLOW_THREADS', 'Annotation', 'Arrow', 'Artist', 'AutoLocator', 'Axes', 'BUFSIZE', 'Button', 'CLIP', 'Circle', 'ComplexWarning', 'DAILY', 'DataSource', 'DateFormatter', 'DateLocator', 'DayLocator', 'ERR_CALL', 'ERR_DEFAULT', 'ERR_DEFAULT2', 'ERR_IGNORE', 'ERR_LOG', 'ERR_PRINT', 'ERR_RAISE', 'ERR_WARN', 'FLOATING_POINT_SUPPORT', 'FPE_DIVIDEBYZERO', 'FPE_INVALID', 'FPE_OVERFLOW', 'FPE_UNDERFLOW', 'FR', 'False_', 'Figure', 'FigureCanvasBase', 'FixedFormatter', 'FixedLocator', 'FormatStrFormatter', 'Formatter', 'FuncFormatter', 'GridSpec', 'HOURLY', 'HourLocator', 'In', 'IndexDateFormatter', 'IndexLocator', 'Inf', 'Infinity', 'LinAlgError', 'Line2D', 'LinearLocator', 'Locator', 'LogFormatter', 'LogFormatterExponent', 'LogFormatterMathtext', 'LogLocator', 'MAXDIMS', 'MINUTELY', 'MO', 'MONTHLY', 'MachAr', 'MaxNLocator', 'MinuteLocator', 'ModuleDeprecationWarning', 'MonthLocator', 'MultipleLocator', 'NAN', 'NINF', 'NZERO', 'NaN', 'Normalize', 'NullFormatter', 'NullLocator', 'Out', 'PINF', 'PZERO', 'PackageLoader', 'PolarAxes', 'Polygon', 'RAISE', 'RRuleLocator', 'RankWarning', 'Rectangle', 'SA', 'SECONDLY', 'SHIFT_DIVIDEBYZERO', 'SHIFT_INVALID', 'SHIFT_OVERFLOW', 'SHIFT_UNDERFLOW', 'SU', 'ScalarFormatter', 'ScalarType', 'SecondLocator', 'Slider', 'Subplot', 'SubplotTool', 'TH', 'TU', 'Tester', 'Text', 'TickHelper', 'True_', 'UFUNC_BUFSIZE_DEFAULT', 'UFUNC_PYVALS_NAME', 'WE', 'WEEKLY', 'WRAP', 'WeekdayLocator', 'Widget', 'YEARLY', 'YearLocator', '_', '__', '___', '__builtin__', '__builtins__', '__doc__', '__name__', '__package__', '__version__', '_dh', '_exit_code', '_i', '_i1', '_i10', '_i11', '_i12', '_i13', '_i14', '_i15', '_i16', '_i2', '_i3', '_i4', '_i5', '_i6', '_i7', '_i8', '_i9', '_ih', '_ii', '_iii', '_oh', '_sh', 'absolute', 'absolute_import', 'acorr', 'add', 'add_docstring', 'add_newdoc', 'add_newdoc_ufunc', 'add_newdocs', 'alen', 'all', 'allclose', 'alltrue', 'alterdot', 'amap', 'amax', 'amin', 'angle', 'annotate', 'any', 'append', 'apply_along_axis', 'apply_over_axes', 'arange', 'arccos', 'arccosh', 'arcsin', 'arcsinh', 'arctan', 'arctan2', 'arctanh', 'argmax', 'argmin', 'argpartition', 'argsort', 'argwhere', 'around', 'array', 'array2string', 'array_equal', 'array_equiv', 'array_repr', 'array_split', 'array_str', 'arrow', 'asanyarray', 'asarray', 'asarray_chkfinite', 'ascontiguousarray', 'asfarray', 'asfortranarray', 'asmatrix', 'asscalar', 'atleast_1d', 'atleast_2d', 'atleast_3d', 'autoscale', 'autumn', 'average', 'axes', 'axhline', 'axhspan', 'axis', 'axvline', 'axvspan', 'bar', 'barbs', 'barh', 'bartlett', 'base_repr', 'bench', 'beta', 'binary_repr', 'bincount', 'binomial', 'bitwise_and', 'bitwise_not', 'bitwise_or', 'bitwise_xor', 'bivariate_normal', 'blackman', 'bmat', 'bone', 'bool8', 'bool_', 'box', 'boxplot', 'broadcast', 'broadcast_arrays', 'broken_barh', 'busday_count', 'busday_offset', 'busdaycalendar', 'byte', 'byte_bounds', 'bytes', 'bytes_', 'c_', 'can_cast', 'cast', 'cbook', 'cdouble', 'ceil', 'center_matrix', 'cfloat', 'char', 'character', 'chararray', 'chisquare', 'cholesky', 'choose', 'cla', 'clabel', 'clf', 'clim', 'clip', 'clongdouble', 'clongfloat', 'close', 'cm', 'cohere', 'colorbar', 'colormaps', 'colors', 'column_stack', 'common_type', 'compare_chararrays', 'complex128', 'complex256', 'complex64', 'complex_', 'complexfloating', 'compress', 'concatenate', 'cond', 'conj', 'conjugate', 'connect', 'contour', 'contourf', 'convolve', 'cool', 'copper', 'copy', 'copysign', 'copyto', 'corrcoef', 'correlate', 'cos', 'cosh', 'count_nonzero', 'count_pri', 'count_sec', 'cov', 'cross', 'csd', 'csingle', 'csv2rec', 'ctypeslib', 'cumprod', 'cumproduct', 'cumsum', 'date2num', 'datestr2num', 'datetime', 'datetime64', 'datetime_as_string', 'datetime_data', 'dedent', 'deg2rad', 'degrees', 'delaxes', 'delete', 'demean', 'deprecate', 'deprecate_with_doc', 'det', 'detrend', 'detrend_linear', 'detrend_mean', 'detrend_none', 'diag', 'diag_indices', 'diag_indices_from', 'diagflat', 'diagonal', 'diff', 'digitize', 'disconnect', 'disp', 'display', 'dist', 'dist_point_to_segment', 'distances_along_curve', 'divide', 'division', 'docstring', 'dot', 'double', 'drange', 'draw', 'draw_if_interactive', 'dsplit', 'dstack', 'dtype', 'e', 'ediff1d', 'eig', 'eigh', 'eigvals', 'eigvalsh', 'einsum', 'emath', 'empty', 'empty_like', 'entropy', 'epoch2num', 'equal', 'errorbar', 'errstate', 'euler_gamma', 'evaluate_data', 'eventplot', 'exception_to_str', 'exit', 'exp', 'exp2', 'exp_safe', 'expand_dims', 'expm1', 'exponential', 'extract', 'eye', 'f', 'fabs', 'fastCopyAndTranspose', 'fft', 'fft2', 'fftfreq', 'fftn', 'fftpack', 'fftpack_lite', 'fftshift', 'fftsurr', 'figaspect', 'figimage', 'figlegend', 'fignum_exists', 'figsize', 'figtext', 'figure', 'fill', 'fill_between', 'fill_betweenx', 'fill_diagonal', 'find', 'find_common_type', 'findobj', 'finfo', 'fix', 'flag', 'flatiter', 'flatnonzero', 'flatten', 'flexible', 'fliplr', 'flipud', 'float128', 'float16', 'float32', 'float64', 'float_', 'floating', 'floor', 'floor_divide', 'fmax', 'fmin', 'fmod', 'format_parser', 'frange', 'frexp', 'frombuffer', 'fromfile', 'fromfunction', 'fromiter', 'frompyfunc', 'fromregex', 'fromstring', 'full', 'full_like', 'fv', 'gamma', 'gca', 'gcf', 'gci', 'generic', 'genfromtxt', 'geometric', 'get', 'get_array_wrap', 'get_backend', 'get_cmap', 'get_current_fig_manager', 'get_figlabels', 'get_fignums', 'get_include', 'get_ipython', 'get_numarray_include', 'get_plot_commands', 'get_printoptions', 'get_scale_docs', 'get_scale_names', 'get_sparse_matrix', 'get_state', 'get_xyz_where', 'getbuffer', 'getbufsize', 'geterr', 'geterrcall', 'geterrobj', 'getfigs', 'getp', 'ginput', 'gradient', 'gray', 'greater', 'greater_equal', 'grid', 'griddata', 'gumbel', 'half', 'hamming', 'hanning', 'helper', 'hexbin', 'hfft', 'hist', 'hist2d', 'histogram', 'histogram2d', 'histogramdd', 'hlines', 'hold', 'hot', 'hsplit', 'hstack', 'hsv', 'hypergeometric', 'hypot', 'i0', 'identity', 'ifft', 'ifft2', 'ifftn', 'ifftshift', 'ihfft', 'iinfo', 'imag', 'imread', 'imsave', 'imshow', 'in1d', 'index_exp', 'indices', 'inexact', 'inf', 'info', 'infty', 'inner', 'insert', 'inside_poly', 'int0', 'int16', 'int32', 'int64', 'int8', 'int_', 'int_asbuffer', 'intc', 'integer', 'interactive', 'interp', 'intersect1d', 'intp', 'inv', 'invert', 'ioff', 'ion', 'ipmt', 'irfft', 'irfft2', 'irfftn', 'irr', 'is_busday', 'is_closed_polygon', 'is_numlike', 'is_string_like', 'isclose', 'iscomplex', 'iscomplexobj', 'isfinite', 'isfortran', 'ishold', 'isinf', 'isinteractive', 'isnan', 'isneginf', 'isposinf', 'ispower2', 'isreal', 'isrealobj', 'isscalar', 'issctype', 'issubclass_', 'issubdtype', 'issubsctype', 'isvector', 'iterable', 'ix_', 'jet', 'kaiser', 'kron', 'l1norm', 'l2norm', 'lapack_lite', 'laplace', 'ldexp', 'left_shift', 'legend', 'less', 'less_equal', 'levypdf', 'lexsort', 'linalg', 'linspace', 'little_endian', 'load', 'loads', 'loadtxt', 'locator_params', 'log', 'log10', 'log1p', 'log2', 'logaddexp', 'logaddexp2', 'logical_and', 'logical_not', 'logical_or', 'logical_xor', 'logistic', 'loglog', 'lognormal', 'logseries', 'logspace', 'longcomplex', 'longdouble', 'longest_contiguous_ones', 'longest_ones', 'longfloat', 'longlong', 'lookfor', 'lstsq', 'ma', 'mafromtxt', 'margins', 'mask_indices', 'mat', 'math', 'matplotlib', 'matrix', 'matrix_power', 'matrix_rank', 'matshow', 'maximum', 'maximum_sctype', 'may_share_memory', 'mean', 'median', 'memmap', 'meshgrid', 'mgrid', 'min_scalar_type', 'minimum', 'minorticks_off', 'minorticks_on', 'mintypecode', 'mirr', 'mlab', 'mod', 'modf', 'movavg', 'mpl', 'msort', 'multinomial', 'multiply', 'multivariate_normal', 'mx2num', 'nan', 'nan_to_num', 'nanargmax', 'nanargmin', 'nanmax', 'nanmean', 'nanmin', 'nanstd', 'nansum', 'nanvar', 'nbytes', 'ndarray', 'ndenumerate', 'ndfromtxt', 'ndim', 'ndindex', 'nditer', 'negative', 'negative_binomial', 'nested_iters', 'new_figure_manager', 'newaxis', 'newbuffer', 'nextafter', 'noncentral_chisquare', 'noncentral_f', 'nonzero', 'norm', 'norm_flat', 'normal', 'normalize', 'normpdf', 'not_equal', 'np', 'nper', 'npv', 'num2date', 'num2epoch', 'number', 'numpy', 'obj2sctype', 'object0', 'object_', 'ogrid', 'ones', 'ones_like', 'os', 'outer', 'over', 'packbits', 'pad', 'pareto', 'partition', 'path_length', 'pause', 'pcolor', 'pcolormesh', 'percentile', 'permutation', 'pi', 'pie', 'piecewise', 'pink', 'pinv', 'pkgload', 'place', 'plot', 'plot_date', 'plotfile', 'plotting', 'plt', 'pmt', 'poisson', 'polar', 'poly', 'poly1d', 'poly_below', 'poly_between', 'polyadd', 'polyder', 'polydiv', 'polyfit', 'polyint', 'polymul', 'polysub', 'polyval', 'power', 'ppmt', 'prctile', 'prctile_rank', 'prepca', 'primary', 'print_function', 'prism', 'prod', 'product', 'promote_types', 'psd', 'ptp', 'put', 'putmask', 'pv', 'pylab', 'pylab_setup', 'pyplot', 'qr', 'quit', 'quiver', 'quiverkey', 'r_', 'rad2deg', 'radians', 'rand', 'randint', 'randn', 'random', 'random_integers', 'random_sample', 'ranf', 'rank', 'rate', 'ravel', 'ravel_multi_index', 'rayleigh', 'rc', 'rcParams', 'rcParamsDefault', 'rc_context', 'rcdefaults', 'read_data', 'real', 'real_if_close', 'rec', 'rec2csv', 'rec_append_fields', 'rec_drop_fields', 'rec_join', 'recarray', 'recfromcsv', 'recfromtxt', 'reciprocal', 'record', 'register_cmap', 'relativedelta', 'remainder', 'repeat', 'require', 'reshape', 'resize', 'restoredot', 'result_type', 'rfft', 'rfft2', 'rfftfreq', 'rfftn', 'rgrids', 'right_shift', 'rint', 'rk4', 'rms_flat', 'roll', 'rollaxis', 'roots', 'rot90', 'round_', 'row_stack', 'rrule', 's_', 'safe_eval', 'sample', 'save', 'savefig', 'savetxt', 'savez', 'savez_compressed', 'sca', 'scatter', 'sci', 'sctype2char', 'sctypeDict', 'sctypeNA', 'sctypes', 'searchsorted', 'secondary', 'seed', 'segments_intersect', 'select', 'semilogx', 'semilogy', 'set_cmap', 'set_numeric_ops', 'set_printoptions', 'set_state', 'set_string_function', 'setbufsize', 'setdiff1d', 'seterr', 'seterrcall', 'seterrobj', 'setp', 'setxor1d', 'shape', 'short', 'show', 'show_config', 'shuffle', 'sign', 'signbit', 'signedinteger', 'silent_list', 'sin', 'sinc', 'single', 'singlecomplex', 'sinh', 'size', 'slogdet', 'slopes', 'solve', 'sometrue', 'sort', 'sort_complex', 'source', 'spacing', 'specgram', 'spectral', 'split', 'spring', 'spy', 'sqrt', 'square', 'squeeze', 'stackplot', 'standard_cauchy', 'standard_exponential', 'standard_gamma', 'standard_normal', 'standard_t', 'std', 'stem', 'step', 'stineman_interp', 'str_', 'streamplot', 'string0', 'string_', 'strpdate2num', 'subplot', 'subplot2grid', 'subplot_tool', 'subplots', 'subplots_adjust', 'subtract', 'sum', 'summer', 'suptitle', 'svd', 'swapaxes', 'switch_backend', 'sys', 'table', 'take', 'tan', 'tanh', 'tensordot', 'tensorinv', 'tensorsolve', 'test', 'text', 'thetagrids', 'tick_params', 'ticklabel_format', 'tight_layout', 'tile', 'timedelta64', 'title', 'trace', 'transpose', 'trapz', 'tri', 'triangular', 'tricontour', 'tricontourf', 'tril', 'tril_indices', 'tril_indices_from', 'trim_zeros', 'tripcolor', 'triplot', 'triu', 'triu_indices', 'triu_indices_from', 'true_divide', 'trunc', 'twinx', 'twiny', 'typeDict', 'typeNA', 'typecodes', 'typename', 'ubyte', 'ufunc', 'uint', 'uint0', 'uint16', 'uint32', 'uint64', 'uint8', 'uintc', 'uintp', 'ulonglong', 'unicode0', 'unicode_', 'uniform', 'union1d', 'unique', 'unpackbits', 'unravel_index', 'unsignedinteger', 'unwrap', 'use_fastnumpy', 'ushort', 'vander', 'var', 'vdot', 'vector_lengths', 'vectorize', 'vlines', 'void', 'void0', 'vonmises', 'vsplit', 'vstack', 'waitforbuttonpress', 'wald', 'warnings', 'weibull', 'where', 'who', 'window_hanning', 'window_none', 'winter', 'write_output', 'xcorr', 'xkcd', 'xlabel', 'xlim', 'xscale', 'xticks', 'ylabel', 'ylim', 'yscale', 'yticks', 'zeros', 'zeros_like', 'zipf']

최종 수정 버전


In [13]:
def evaluate_data(data, lower=100, upper=300):
    '''Counts data points in three bins.'''
    smaller = 0
    between = 0
    bigger = 0
    
    for length in data:
        if length < lower:
            smaller = smaller + 1
        elif lower < length < upper:
            between = between + 1
        elif length > upper:
            bigger = 1
    return smaller, between, bigger

def read_data(filename):
    '''Reads neuron lengths from a text file.'''
    primary, secondary = [], []
    
    with open(filename) as f:
        for line in f:
            category, length = line.split('\t')
            length = float(length)
            if category == 'Primary':
                primary.append(length)
            elif category == 'Secondary':
                secondary.append(length)
    return primary, secondary

def write_output(filename, count_pri, count_sec):
    '''Writes counted values to a file.'''
    with open(filename, 'w') as output:
        output.write('category <100 100-300 >300\n')
        output.write('Primary : %5i %5i %5i\n' % count_pri)
        output.write('Secondary: %5i %5i %5i\n' % count_sec)
        
primary, secondary = read_data('12-debugging/neuron_data.txt')
count_pri = evaluate_data(primary)
print count_pri
count_sec = evaluate_data(secondary)
write_output('12-debugging/results.txt', count_pri, count_sec)


(2, 2, 1)

In [25]:
!head -n 9 12-debugging/neuron_data.txt











In [8]:
!cat 12-debugging/results.txt


category <100 100-300 >300
Primary :     2     2     1
Secondary:    12    11     1

12.3.3 Handling Exceptions


In [15]:
try:
    a = float(raw_input('Insert a number:'))
    print a
except ValueError:
    print "You haven't inserted a number. Please retry."
except ArithmeticError, e:
    print 'ArithmeticError', e
except Exception as e:
    print e


Insert a number:aaa
You haven't inserted a number. Please retry.

In [17]:
a = float(raw_input('Insert a number:'))


Insert a number:AA
---------------------------------------------------------------------------
ValueError                                Traceback (most recent call last)
<ipython-input-17-a808eed9f169> in <module>()
----> 1 a = float(raw_input('Insert a number:'))

ValueError: could not convert string to float: AA

In [19]:
try:
    a = float(raw_input('Insert a number:'))
    print a
except ValueError as e:
    print 'value error', e
except Exception as e:
    print e


Insert a number:aaa
value error could not convert string to float: aaa

In [21]:
try:
    print '예외를 유발할 수 있는 구문'
except:
    print '예외 처리를 수행하는 구문'
else:
    print '예외가 발생하지 않을 경우 수행할 구문'


예외를 유발할 수 있는 구문
예외가 발생하지 않을 경우 수행할 구문

In [22]:
try:
    f = open('ch10.ipynb', 'r')
except IOError as e:
    print e
else:
    print 'ok. file open success.\n', f.read(100)


ok. file open success.
{
 "metadata": {
  "name": "",
  "signature": "sha256:20a3a0e2c55488f434134048b0d78a86c0fe660d588f1b

In [26]:
try:
    f = open('ch.ipynb', 'r')
except IOError as e:
    print e
else:
    print 'ok. file open success.\n', f.read(100)


[Errno 2] No such file or directory: 'ch.ipynb'

In [33]:
try:
    filename = raw_input('Insert a filename:')
    in_file = open(filename)
except IOError:
    print 'The filename %s has not been found.' % filename
else:
    for line in in_file:
        print line
    in_file.close()


Insert a filename:12-debugging/results.txt
category <100 100-300 >300

Primary :     2     2     1

Secondary:    12    11     1

10.3.4 When There Is No Error Message

셜록홈즈는 연역적인 접근 방법을 사용

  1. collecting facts
  2. excludes possibilities
  3. draw logical conclusion

How to investigate the program in programming

  • function A, function C: ok
  • problem: function B
  1. comparing input and output of your program
  2. adding print statements
  3. using the Python debugger.

Comparing Input and Output


책 잘 만들었네. 구성이 좋다.

  • 어떻게 프로그램을 디버깅하는지?
  • 어떻게 좋은 프로그램을 만드는지?
  • 이런걸 설명해주는 책들이 많지 않은데.. 참 잘 설명해 놓음


In [34]:
!cat 12-debugging/neuron_data.txt


































In [35]:
!cat 12-debugging/results.txt


category <100 100-300 >300
Primary :     2     2     1
Secondary:    12    11     1

In [44]:
primary, secondary = read_data('12-debugging/neuron_data.txt')

In [46]:
print primary


[441.462, 139.907, 16.385, 355.702, 53.566, 327.777, 405.622, 256.088]

In [45]:
print secondary


[29.031, 46.009, 40.932, 34.952, 82.248, 39.819, 144.143, 74.495, 93.231, 202.075, 142.301, 99.782, 104.875, 118.54, 63.477, 76.063, 253.321, 125.41, 58.876, 226.57, 362.695, 149.753, 140.738, 214.723]

In [47]:
count_pri = evaluate_data(primary)

In [48]:
count_sec = evaluate_data(secondary)

In [49]:
count_pri


Out[49]:
(2, 2, 1)

In [50]:
count_sec


Out[50]:
(12, 11, 1)

In [54]:
print count_sec


(12, 11, 1)

In [52]:
write_output('12-debugging/results.txt', count_pri, count_sec)

In [53]:
!cat 12-debugging/results.txt


category <100 100-300 >300
Primary :     2     2     1
Secondary:    12    11     1

Using the Python Debugger

  • IPython 소개 - pdb 부분
  • 개인적으로 pdb 보다는 PyCharm의 debug 기능을 사용한다.
  • 왜냐하면 일단 GUI로 되어 있어서 명령어에 대한 부담감이 없으며 볼 수 있는 정보가 훨씬 많다.

12.4 EXAMPLES

Example 12.1 ImportError

  • Check the spelling of the module name.
  • verify the directory you started the program from
  • 원하는 곳에 모듈이 존재하냐?

In [2]:
import sys
from pprint import pprint
pprint(sys.path)


['',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python27.zip',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/plat-darwin',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/plat-mac',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/plat-mac/lib-scriptpackages',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/lib-tk',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/lib-old',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/lib-dynload',
 '/Users/re4lfl0w/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages',
 '/Users/re4lfl0w/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/PIL',
 '/Applications/Canopy.app/appdata/canopy-1.3.0.1715.macosx-x86_64/Canopy.app/Contents/lib/python2.7/site-packages',
 '/Users/re4lfl0w/Library/Enthought/Canopy_64bit/User/lib/python2.7/site-packages/IPython/extensions',
 '/Users/re4lfl0w/.ipython',
 '/Users/re4lfl0w/Documents/ipython_private/scripts/']
  • 저 리스트 중에 모듈이 존재하는 위치가 없다면 PYTHONPATH 환경변수에 추가해 줘야 한다. 아니면 sys.path에 추가해주던지
  • Check whether you can import the module itself in the first place: import X.
  • Then try whether you can import variables and functions from within from X import Y.
  • subdirectory에서 import 하려고 하는가? 그 폴더 밑에는 반드시 __init__.py 가 존재해야 subdirectory로 인식한다.
  • 중복된 모듈 이름을 확인하라.
    • import string을 했는데 내가 ipython을 실행시킨 위치에 string.py 가 존재한다면 내가 만든 string.py가 실행된다. 내가 원래 원했던 목적은 Standard Library의 string을 import 하고 싶었던 것이다. 기본은 sys.path에 있는 것이 실행되지만 자신의 현재 디렉토리에 있는 것이 나중에 오버라이딩되서 먼저 저장되어 있던 Standard Library인 string이 삭제되고 현재 디렉토리에 내가 만든 string이 적용이 되기 때문이다.
    • import *는 비추. 왠만하면 모두 명확히 함수이름까지 써주자. 나중에 어디에서 문제가 발생했는지 찾다가 스트레스 받는다.

Example 12.2 ValueError

  • 연산을 하기 위한 2변수 중에서 양립할 수 없을 경우 발생
  • integer + string 같은 경우
  • convert를 해줘야 한다. int()나 float()으로.

In [3]:
a = '1'
b = '2'
print a, b
result = a + b


1 2

In [5]:
print type(a), type(b)
result = a + b


<type 'str'> <type 'str'>

In [6]:
type([1,2,3])


Out[6]:
list

In [7]:
type(4)


Out[7]:
int

Example 12.3 IndexError

  • list나 tuple, dictionary에서 엘리먼트를 찾을 수 없을 때
  • print로 전체 데이터를 확인해라

In [23]:
data = [1,2,3]

In [24]:
print data[3]


---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-24-02a63bb515d5> in <module>()
----> 1 print data[3]

IndexError: list index out of range
  • dictionary인 경우는 keys()를 써줘라

In [13]:
print data


[1, 2, 3]

In [20]:
d = {'name':'Jo',
     'Age':20,
     'Sex':'M'}

In [21]:
print d


{'Age': 20, 'name': 'Jo', 'Sex': 'M'}

In [22]:
print d.keys()


['Age', 'name', 'Sex']

Example 12.4 Writing Readable Code

  • 변수명이 길어지더라도 쉽게 읽을 수 있게 만들어야 나중에 코드를 수정할 때 편하다.
  • Good code modularization: chapter10, 11
  • Good organization of a programming project: chapter15
  • Use descriptive names for variables and functions
for line in sequence_file:

for l in f:
  • 변수는 어떤 데이터인지 명확히 설명할 수 있어야 좋다. text, seq_length가 number 보다 좋다.
  • 함수명은 동사로: read_sequence_file
  • Write comments: 어떤 함수의 역할인지 주석을 달아라. 꼭 필요한 곳에만 달자.
  • Avoid the import * statement: ```python from math import *

from math import pi, sin, cos ```

  • 밑의 표현이 훨씬 좋다. 명확히 써줘야 한다. import *를 쓰게 되면 나중에 의도치않은 함정에 걸리게 된다.
  • PEP8 맞춰서 써라(Chapter15)

12.5 Testing yourself

Exercise 12.1 Debugging Python Session in Section 12.2.2

Exercise 12.2 Use of try...except statements

Exercise 12.3 Exception Handling in dealing with files and numbers

Exercise 12.4 Nested try...except statements

Exception Handling in dealing with standard input and numbers


In [ ]: