-2

At first I was getting a syntax error with this code:

eval('A'+str(x)+' = np.flip(cv2.imread(r"'+str(path)+'\\'+str(image[x-firstImage])+'", cv2.IMREAD_UNCHANGED),1)')

I thought perhaps I messed something up so I tried to start barebones (literally just reading in one image) from:

import numpy as np
import cv2

x = 1

#Number of pixels in img
column = 500
row = 200

A1 = np.zeros((row,column)) 

path = r'C:\Users\Boyon\Desktop\PhotoFile'
image = 'photo01.tif'

eval('A'+str(x)+' = cv2.imread(r"'+str(path)+'\\'+str(image)+'",cv2.IMREAD_UNCHANGED)') 

but I'm still getting a syntax error. What the code is reading is

A1 = cv2.imread(r"C:\Users\Boyon\Desktop\PhotoFile\photo01.tif",cv2.IMREAD_UNCHANGED)

which I know works because I had done it just a couple of weeks ago, so I don't know if this is an issue fundamentally with eval? My knowledge on it isn't great and so I'm not sure if what I input into it doesn't work. The error code is as follows:

  File "<string>", line 1
    A1 = cv2.imread(r"C:\Users\Boyon\Desktop\PhotoFile\photo01.tif")
       ^
SyntaxError: invalid syntax
Boyon
  • 21
  • 1
  • 7
  • 2
  • 2
    Why are you trying to `eval` it? Why not just `a1 = cv2.imread(f"{path}\\{image}",cv2.IMREAD_UNCHANGED)`? – Carcigenicate Aug 19 '20 at 00:08
  • @Yatin invalid syntax – Boyon Aug 19 '20 at 00:10
  • 2
    @Boyon, the _full_ error message, with details and traceback, please. See [ask]. – ChrisGPT was on strike Aug 19 '20 at 00:11
  • @Carcigenicate Well Im trying to reproduce another code that uses eval statements, and later on in the program it sorta requires them to be formatted like what I have so I'm just trying to get it to work (reading in just one image) first before I plug it back into my main code and continue on – Boyon Aug 19 '20 at 00:11
  • 1
    @Boyon If I were you, I'd be highly suspicious of any source that's dynamically creating variables using `eval`. There's many different ways of achieving that effect, and dynamic variable creation is probably the worst possible option. Anyways, IIRC, the issue is that `eval` expects an expression, which `=` isn't. You need to use `exec` instead (Again, iirc. I don't use either function because they have very few good use-cases). – Carcigenicate Aug 19 '20 at 00:13
  • @Carcigenicate Understood, thanks for the explanation. Could I then ask you for a recommendation? My issue is, later on in the code these arrays are references as "Array#[i]" where both # and i are varying, problem is I didn't know how to achieve having # vary unless using said eval statements. Can you recommend a better process? – Boyon Aug 19 '20 at 00:17
  • @Boyon Instead of creating `A1`, `A2`, `A3`. . . variables, put the objects into a list and refer to them as `images[0]`, `images[1]`, `images[2]`. . . That way, you can use all the list operations on them to filter, iterate them without manually building strings to do a variable lookup. If you have two dimensions (varying letters and numbers), a two dimensional list or another structure simulating one would work well. Then you have `images[0][0]`, `images[0][1]`. . ., or again, just by normal iteration using a `for`. – Carcigenicate Aug 19 '20 at 00:19
  • @Carcigenicate I see what you mean. I'm just wondering, these arrays under A1...An are n x m matrices. I see what you mean if you have changing letters & numbers, luckily just only the number. So would I be able to update the list, i.e A1..An while also indexing the 2d matrices within? – Boyon Aug 19 '20 at 00:24
  • Sorry, just to clarify because I can't tell from your last comment: do you need a 2D structure, or just a 1D list? You mention only needing a number to index, but also mention 2D matrices. – Carcigenicate Aug 19 '20 at 00:27
  • @Carcigenicate Not a problem, perhaps I should've been more clear. In essence I need an array of length n, where each element is a 2d array. Problem is I wouldn't know how to index both the initial array, and then elements within the 2d array. – Boyon Aug 19 '20 at 00:31
  • I mean I guess I can just use a 3d array, I dont really know wtf I was thinking but I guess this would work just as well – Boyon Aug 19 '20 at 00:47
  • Ya, a 1D list of 2D matrices is essentially a 3D list/array, so you could just access it like `images[1][0][0]` to get the `0,0`th element of the matrix at index 1. See [this gist](https://gist.github.com/carcigenicate/475b72cc3516143f1c4cac4012b62d5e) for an example. – Carcigenicate Aug 19 '20 at 00:50
  • Yes thats exactly it man! I think I was overthinking about it waaay too much but that'll do. Thanks a ton for the ideas, I'll probably be deleting this post soon as it wasn't very helpful and to save me the shame haha, many thanks again ! – Boyon Aug 19 '20 at 00:54
  • Boyon, please don't delete questions just because you consider them not useful to yourself (or, worse, though I'm not accusing *you* of this, just because the asker has gotten the information they need and see no further need for the question). The intent of SO is to be a repository of questions and answers for everyone else in the future as well, and deleting questions "breaks" that feature. – paxdiablo Aug 19 '20 at 00:56
  • @paxdiablo That I understand for sure, it just seems as though it didn't get greeted very well, and to which reason I don't really know as I seldom post on here – Boyon Aug 19 '20 at 01:04
  • Given the reason "debugging details needed", I suspect it's because you hadn't shown the exception output. Since you've now added that, I think your question has everything it needs. It may or may not be re-opened (I've voted for that) but, even closed, it still has useful content. – paxdiablo Aug 19 '20 at 02:08
  • Ah understood, thanks for informing me – Boyon Aug 19 '20 at 02:27

1 Answers1

1

You cannot eval assignments, eval is basically just for evaluating things normally found on the right of an assignment statement.

You probably should be using exec for this, provided you understand and mitigate the risks. For example, see the following code, loosely based on yours:

path = r'C:\Users\Boyon\Desktop\PhotoFile'
image = 'photo01.tif'

x = 1
exec('A'+str(x)+' = r"'+str(path)+'\\'+str(image)+'"')
print('EXEC', A1, '\n')

x = 2
A1 = eval(r"str(path)+'\\'+str(image)+str(x)")
print('EVAL1', A1, '\n')

x = 3
eval('A'+str(x)+' = r"'+str(path)+'\\'+str(image)+'"')
print('EVAL2', A1, '\n')

The first call, exec, will work, and set the global A1. The second will also work because you're not attempting an assignment. The third will fail:

EXEC C:\Users\Boyon\Desktop\PhotoFile\photo01.tif

EVAL1 C:\Users\Boyon\Desktop\PhotoFile\photo01.tif2

Traceback (most recent call last):
  File "testprog.py", line 13, in <module>
    eval('A'+str(x)+' = r"'+str(path)+'\\'+str(image)+'"')
  File "<string>", line 1
    A3 = r"C:\Users\Boyon\Desktop\PhotoFile\photo01.tif"
       ^
SyntaxError: invalid syntax

Just keep in mind you can't use exec to set local variables inside a function, see here for details but it's basically caused by the fact that the locals dictionary passed by default to exec is a copy of the actual locals (a dictionary built for heavily optimised internal structures).

However, you can pass your own dictionary to exec to be treated as the locals and then use that to get at the variables that were set - there's just no easy way (or any way, really) to echo that back to the actual locals.

The following code shows how to do this:

path = '/tmp/PhotoFile'
image = 'photo01.tif'

# Construct dictionary to take "locals".

mydict = {}
for i in range(10):
    exec(f"a{i} = '{path}/photo{9-i:02d}'", globals(), mydict)

# Show how to get at them.

for key in mydict:
    print(f"My dictionary: variable '{key}' is '{mydict[key]}'")

And the output is:

My dictionary: variable 'a0' is '/tmp/PhotoFile/photo09'
My dictionary: variable 'a1' is '/tmp/PhotoFile/photo08'
My dictionary: variable 'a2' is '/tmp/PhotoFile/photo07'
My dictionary: variable 'a3' is '/tmp/PhotoFile/photo06'
My dictionary: variable 'a4' is '/tmp/PhotoFile/photo05'
My dictionary: variable 'a5' is '/tmp/PhotoFile/photo04'
My dictionary: variable 'a6' is '/tmp/PhotoFile/photo03'
My dictionary: variable 'a7' is '/tmp/PhotoFile/photo02'
My dictionary: variable 'a8' is '/tmp/PhotoFile/photo01'
My dictionary: variable 'a9' is '/tmp/PhotoFile/photo00'
paxdiablo
  • 854,327
  • 234
  • 1,573
  • 1,953
  • Thanks for the tips. I may need to fundamentally change this then because I would need it to set a local var in a function, so I guess neither will fly. – Boyon Aug 19 '20 at 00:21
  • Just read your updated answer, thanks man, makes tons of sense. As mentioned, I'll have to fundamentally re-work the whole code then. Cheers – Boyon Aug 19 '20 at 00:28