NameError: name 'product' is not defined ; error in python3 but works in python2

The code shown below is part of a lengthy script. This code works fine in python2 but in python3 it gives NameError. What changes should i do?

def TensorDotProduct(*TensorList):
    ''' dot product of mupltiple tensors '''
    product = TensorList[-1]
    print("LENGTH",len(product))
    for tensor in TensorList[:-1][::-1]:
        product = _TensorDotProduct_(tensor,product)
        print("PRODUCT",product)
    return product


def _TensorDotProduct_(Tij,Tjk):
    ''' dot product of two tensors '''
    ni,nj = Tij.shape[:2]
    mj,nk = Tjk.shape[:2]
    if mj != nj:
       print ("tensor shape mismatched",nj,mj)
       return 0
    else:
       TensorExpr = [] #hold the calculation to save computing time
       for i in range(ni):
           VectorExpr = []
           for k in range(nk):
               ############### Einstein Summation #################
               SumConvention = '+'.join([\
                       'Tij[%d,%d]*Tjk[%d,%d]'%(i,j,j,k)\
                                             for j in range(nj)])
               ####################################################
               VectorExpr.append(SumConvention)
           VectorExpr = '['+','.join(VectorExpr)+']'
           TensorExpr.append(VectorExpr)
       TensorExpr = '['+','.join(TensorExpr)+']'
       exec('product='+TensorExpr)
       return array(product)

I am getting error as shown below: :point_down:

Traceback (most recent call last):
  File "/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py", line 118, in <module>
    uc=data.ucon()
       ^^^^^^^^^^^
  File "/home/raman/Pictures/MikiFor2to3/pyfiles/read_data.py", line 77, in ucon
    gamma = self.lorentz_gamma()
            ^^^^^^^^^^^^^^^^^^^^
  File "/home/raman/Pictures/MikiFor2to3/pyfiles/read_data.py", line 67, in lorentz_gamma
    vcov = Transpose( TensorDotProduct(gcov,vcon) )
                      ^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/raman/Pictures/MikiFor2to3/pyfiles/metric.py", line 464, in TensorDotProduct
    product = _TensorDotProduct_(tensor,product)
              ^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^
  File "/home/raman/Pictures/MikiFor2to3/pyfiles/metric.py", line 490, in _TensorDotProduct_
    return array(product)
                 ^^^^^^^
NameError: name 'product' is not defined

Refactor to avoid arbitrary code execution CVEs and other inevitable bugs that arise from using exec:

   exec('product='+TensorExpr)

What do you mean by refactor ? What should i change in code?

_TensorDotProduct_ is building a string that’s an expression, then prefixing 'product=' onto it to make it look like an assignment state, and executing it with exec('product='+TensorExpr). (Yuck!)

The expectation is that it’ll evaluate the expression and assign the result to product, a variable whose value can be passed to array: return array(product).

However, it doesn’t work like that in Python 3.

The simplest fix might be to use eval instead, replacing exec('product='+TensorExpr) with product = eval(TensorExpr). (Still yuck, but less so!)

1 Like

Why do you build and execute a string like that?

You may have noticed people commenting, opaquely, about exec()
changing its behaviour in Python 3 and eval() being suggested, and
both being considered a poor way to do things (viz, the techincal
remarks such as “Yuck!”).

This is because constructing expressions as strings for evaluation is
error prone, very error prone, and if you’re starting with
foreign/externally sources inputs, often subject to exploitation if
you’re even slightly careless and the attack sufficiently devious.

I suggest that instead of eval()ing or exec()ing this expression
you’ve laboriously constructed, you just execute the things you’re
assembling directly like any other normal function would do.

For example, looking at your _TensorDotProduct_(Tij,Tjk) function
below:

 def _TensorDotProduct_(Tij,Tjk):
     ''' dot product of two tensors '''
     [...]
        TensorExpr = [] #hold the calculation to save computing time
        for i in range(ni):
            VectorExpr = []
            for k in range(nk):
                ############### Einstein Summation #################
                SumConvention = '+'.join([\
                        'Tij[%d,%d]*Tjk[%d,%d]'%(i,j,j,k)\
                                              for j in range(nj)])

I am converting a lengthy python2 script to python3. This script is used for analyzing output data of Atheena++ astrophysical code. I don’t know why these earlier coders have executed a string like that.

@MRAB Thank You, this worked fine for me.

If this is the general pattern of the code you are trying to convert, it would probably be better to rewrite the entire script. These entire two functions you are showing can be replaced by one or two lines of code using numpy, which you appear to already be using anyway. Specifically, this is a valid implementation of TensorDotProduct from what I can tell:

def TensorDotProduct(*TensorList):
    ''' dot product of mupltiple tensors '''
    product = TensorList[-1]
    for tensor in TensorList[:-1][::-1]:
        product = tensor @ product
    return product

And _TensorDotProduct_ can be deleted. (and there probably is a convenience function somewhere in numpy that does the job of TensorDotProduct)

And if it isn’t quite what you need because of the way arrays with more than 2 dimension are dealt with, use tensordot or einsum to replace _TensorDotProduct_

2 Likes

My python3 code for plotting is shown below :point_down: but in my directory there is no output being saved although terminal says (‘Saving frame’, ‘image.0000.png’)
(‘Saving frame’, ‘balongphi.0000.png’) at the end of terminal output. :innocent:
What changes should i do so that it can work in python3.

# Make, name and save plot
        fname = 'image.%04d.png' % t
        print(('Saving frame', fname))
        plt.savefig(dir + fname,bbox_inches='tight')

#        plt.show()

# Define next plot(s), 
        fig = plt.figure(figsize=(20, 7))
#    ax = plt.subplot(111)

# Plot B_p or B_phi at chosen R, Theta in Phi direction
        bporbphi=0#0 for Bp, 1 for B_phi

        plt.clf()
        x1 = [i for i in range (0,nphi)]
        plt.xticks(size=45)#it is fontsize
        plt.yticks(size=45)
        plt.tick_params(width=2, which='both', size=15)
        plt.tick_params(width=4, which='major', size=22)
        plt.minorticks_on()
        plt.xlabel(r"$i(\varphi)$", size=60)

        if bporbphi == 0:
            plt.ylabel(r"B", size=60)
        else:
            plt.ylabel(r"B$_\varphi$", size=60)

        if bporbphi == 0:
            plt.plot(x1, B_p[:,jrms,irms], color='black', ls='dashdot',label=r"B$_{p}$",linewidth=6)
            plt.plot(x1, br[:,jrms,irms], color='r', ls='solid',label=r"B$_{r}$",linewidth=2)
            plt.plot(x1, btheta[:,jrms,irms], color='r', ls='dashed',label=r"B$_{\theta}$",linewidth=3)
            plt.plot(x1, bphi[:,jrms,irms], color='r', ls='dotted',label=r"B$_{\varphi}$",linewidth=3)

# Plot a horizontal black line at y=0        
            x1 = np.linspace(0,70)
            y1 = np.zeros(len(x1))
            plt.plot(x1, y1, color='black', linewidth=1.5)
            plt.legend(loc='best', fontsize='30',ncol=1)

# Make, name and save plot        
        fname = 'balongphi.%04d.png' % t
        print(('Saving frame',fname))
        plt.savefig(dir + fname,bbox_inches='tight')
#        plt.show()

I am getting following warnings while plotiing :point_down:

/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:306: DeprecationWarning: `interp2d` is deprecated in SciPy 1.10 and will be removed in SciPy 1.14.0.

For legacy code, nearly bug-for-bug compatible replacements are
`RectBivariateSpline` on regular grids, and `bisplrep`/`bisplev` for
scattered 2D data.

In new code, for regular grids use `RegularGridInterpolator` instead.
For scattered data, prefer `LinearNDInterpolator` or
`CloughTocher2DInterpolator`.

For more details see
`https://scipy.github.io/devdocs/notebooks/interp_transition_guide.html`

  b2_phi = b_phi(x_stream, z_stream)
('shape(b2_phi)=', (50, 1000))
('shapes of rr,x3,y3=', (288,), (288, 65), (288, 65))
('shape x,z=', (288, 128), (288, 128))
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:864: DeprecationWarning: 'scipy.integrate.cumtrapz' is deprecated in favour of 'scipy.integrate.cumulative_trapezoid' and will be removed in SciPy 1.14.0
  psib = integrate.cumtrapz(np.sqrt(-gdet_grid)*br_grid*2*np.pi,
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:463: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
  density = ax.pcolormesh(x, z, transpose(d[phic,:,:]),cmap=colormap,
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:468: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
  pressuref = ax.pcolormesh(x, z, transpose(prs[phic,:,:]),#/d[phic,:,:]),
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:474: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
  Bpfieldf = ax.pcolormesh(x, z, transpose(B_p[phic,:,:]),
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:478: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
  sigmapf = ax.pcolormesh(x, z, transpose(sigmap[phic,:,:])
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:482: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
  sigmatf = ax.pcolormesh(x, z, transpose(sigmat[phic,:,:])
/home/raman/Pictures/MikiFor2to3/m2c_read_athdata.py:498: UserWarning: The input coordinates to pcolormesh are interpreted as cell centers, but are not monotonically increasing or decreasing. This may lead to incorrectly calculated cell edges, in which case, please supply explicit cell edges to pcolormesh.
  density = ax.pcolormesh(x, z, transpose(d[phic,:,:]),
====================================
++++++++++++++++++++++++++++++++++++
('t,rsph,ryl,zcyl,phic(rad)', 18000.0, np.float64(29.989018067368654), np.float64(24.304815561226043), np.float64(-17.567502531086994), np.float64(0.04908738521234052))
('i,j,phic,theta(rad),line_angle(r,theta)[deg]=,phic(deg)', 127, 89, 0, array([-0.94493217]), array([125.859375]), np.float64(0.0))
('vr,vtheta,vphi_plasmoidcenter=', np.float64(0.019714652411814283), np.float64(0.005371713597019614), np.float64(0.18112011678931444))
++++++++++++++++++++++++++++++++++++
++++++++++++++++++++++++++++++++++++
('t,rsph,rcyl,zcyl,phic(rad)', 18000.0, np.float64(22.2425806999513), np.float64(19.48605976895527), np.float64(10.725011462676814), np.float64(0.0))
('i,j,phic,theta(rad),line_angle(r,theta)[deg]=,phic(deg)', 114, 43, 0, array([1.06765063]), array([61.171875]), np.float64(0.0))
('vr,vtheta,vphi_plasmoidcenter=', np.float64(-0.009327810459887252), np.float64(0.0020440667265488), np.float64(0.1980705800083126))
++++++++++++++++++++++++++++++++++++
====================================
('Saving frame', 'image.0000.png')
('Saving frame', 'balongphi.0000.png')

Are you sure that it’s saving the correct place? Try printing out the full path instead of just the filename.

Also, it’s better to build paths with os.path.join:

        plot_path = os.path.join(dir, fname)
        print('Saving frame', plot_path)
        plt.savefig(plot_path, bbox_inches='tight')

The warnings are for things that you’ll need to update once you’ve got it working because of planned future changes in SciPy.

1 Like

Sorry, I was using wrong dir. :star_struck: once i changes directory name it was saving files in correct folder.

Now i will make changes to eradicate warnings.

In Julia Discourse Forum there is an option to mark a post as solution to thread. How should we can have similar icon in this Python Forum.

We don’t operate like that here; your thanks and your likes on posts are more than sufficient. (Please use the Discourse Feedback category for meta stuff about the forum.)

How should i modify sqrt code devison so that it don’t give RuntimeWarning: ?

/home/raman/Pictures/MikiFor2to3/pyfiles/metric.py:156: RuntimeWarning: invalid value encountered in sqrt
  ei0_mu0 = sqrt(sigma*delta/AA)
/home/raman/Pictures/MikiFor2to3/pyfiles/metric.py:161: RuntimeWarning: invalid value encountered in sqrt
  ei1_mu1 = sqrt(sigma/delta)