Problem with multivariables in string formatting - python-3.x

I have several files in a folder named t_000.png, t_001.png, t_002.png and so on.
I have made a for-loop to import them using string formatting. But when I use the for-loop I got the error
No such file or directory: '/file/t_0.png'
This is the code that I have used I think I should use multiple %s but I do not understand how.
for i in range(file.shape[0]):
im = Image.open(dir + 't_%s.png' % str(i))
file[i] = im

You need to pad the string with leading zeroes. With the type of formatting you're currently using, this should work:
im = Image.open(dir + 't_%03d.png' % i)
where the format string %03s means "this should have length 3 characters and empty space should be padded by leading zeroes".
You can also use python's other (more recent) string formatting syntax, which is somewhat more succinct:
im = Image.open(f"{dir}t_{i:03d}")

You are not padding the number with zeros, thus you get t_0.png instead of t_000.png.
The recommended way of doing this in Python 3 is via the str.format function:
for i in range(file.shape[0]):
im = Image.open(dir + 't_{:03d}.png'.format(i))
file[i] = im
You can see more examples in the documentation.
Formatted string literals are also an option if you are using Python 3.6 or a more recent version, see Green Cloak Guy's answer for that.

Try this:
import os
for i in range(file.shape[0]):
im = Image.open(os.path.join(dir, f't_{i:03d}.png'))
file[i] = im
(change: f't_{i:03d}.png' to 't_{:03d}.png'.format(i) or 't_%03d.png' % i for versions of Python prior to 3.6).
The trick was to specify a certain number of leading zeros, take a look at the official docs for more info.
Also, you should replace 'dir + file' with the more robust os.path.join(dir, file), which would work regardless of dir ending with a directory separator (i.e. '/' for your platform) or not.
Note also that both dir and file are reserved names in Python and you may want to rename your variables.
Also check that if file is a NumPy array, file[i] = im may not be working.

Related

How to parse a configuration file (kind of a CSV format) using LUA

I am using LUA on a small ESP8266 chip, trying to parse a text string that looks like the one below. I am very new at LUA, and tried many similar scripts found at this forum.
data="
-- String to be parsed\r\n
Tiempo1,20\r\n
Tiempo2a,900\r\n
Hora2b,27\r\n
Tiempo2b,20\r\n
Hora2c,29\r\n
Tiempo2c,18\r\n"
My goal would be to parse the string, and return all the configuration pairs (name/value).
If needed, I can modify the syntax of the config file because it is created by me.
I have been trying something like this:
var1,var2 = data:match("([Tiempo2a,]), ([^,]+)")
But it is returning nil,nil. I think I am on the very wrong way to do this.
Thank you very much for any help.
You need to use gmatch and parse the values excluding non-printable characters (\r\n) at the end of the line or use %d+
local data=[[
-- String to be parsed
Tiempo1,20
Tiempo2a,900
Hora2b,27
Tiempo2b,20
Hora2c,29
Tiempo2c,18]]
local t = {}
for k,v in data:gmatch("(%w-),([^%c]+)") do
t[#t+1] = { k, v }
print(k,v)
end

python script to slice filenames to certain length

I am new to python language, trying to write a script that can slice the last characters of filenames to a specific length.
It worked, but for some reason, it denied to proceed and the loop unexpectedly broke giving an error message that the file doesn't exist.
error message: "FileNotFoundError: [WinError 2] The system cannot find the file specified:"
Here is my script, please tell me what is wrong!!!
import os
#define a function to trim latest characters to a specefic length"""
def renamer(folderpath, newlength):
while True:
for filename in os.listdir(folderpath):
root = os.path.splitext(filename)[0]
exten = os.path.splitext(filename)[1]
while len(root) >= newlength:
os.rename(folderpath + '\\' + root + exten, folderpath + '\\' + root[:-1] + exten)
continue
if len(root) <= newlength:
break
I do not like the way you are doing the task, but for solving your problem I am stating the mistake you are doing.
You changed the file from root='Name' to root='Nam' but did not update the value of root. So the next time the loop runs, it again looks for a file 'name' which obviously does not exist, because you renamed it to 'nam'.
So update the value of root also and you will be good to go.
But again, I should mention that you should solve it in some other way.
There are 2 problems here :
It's a good idea to use os.path.join for joining the folder and file name, so that it works on all systems without having to change the code (Eg. - *nix OSes that use / instead of \ as the seperator), instead of concatenating the \\ directly
Like #Illrnr said, the problem is that after the first rename (eg. abcdefgh.png to abcdefg.png), the code will continue looking for the old filename (abcdefgh.png) and this raises the error.
Using a while loop to keep shortening it one character at a time is complicating your logic, and will increase the runtime of your code a lot too with so many calls to rename - you can shorten it to required length in one go without all those loops and tracking length etc etc...
Try this and see if you understand the code:
import os
def renamer(folderpath, newlength):
for filename in os.listdir(folderpath):
root, exten = os.path.splitext(filename)
if len(root)>newlength:
oldname = os.path.join(folderpath, root+exten)
newname = os.path.join(folderpath, root[:newlength]+exten)
os.rename(oldname, newname)
print(f"Shortened {oldname} to {newname}")

How to switch the base of a path using pathlib?

I am trying to get a part of a path by removing the base, currently this is what I'm doing:
original = '/tmp/asd/asdqwe/file'
base = '/tmp/asd/'
wanted_part = original.strip(base)
Unfortunately, instead of getting 'asdqwe/file' I'm getting 'qwefile', for some reason strip works weird and I don't get it.
The best solution for my problem would be using pathlib.Path because my function gets its proprieties as paths, and the return value converting the trimmed string into Path after adding a new base path.
But if no pathlib solution is available a string one would also be great, currently I'm dealing with a weird bug...
You are misinterpreting how str.strip works. The method will remove all characters specified in the argument from the "edges" of the target string, regardless of the order in which they are specified:
original = '/tmp/asd/asdqwe/file'
base = '/tmp/asd/'
wanted_part = original.strip(base)
print(wanted_part)
# qwe/file
What you would like to do is probably a slicing:
wanted_part = original[len(base):]
print(wanted_part)
# asdqwe/file
Or, using pathlib:
from pathlib import Path
original = Path('/tmp/asd/asdqwe/file')
base = Path('/tmp/asd/')
wanted_part = original.relative_to(base)
print(wanted_part)
# asdqwe/file
strip will remove a sequnce of chars, not a string prefix or suffix, so it will keep removing anychars in the sequence you passed. Instaed you can test if the original starts with your base and if it does then just take the remaining chars of the string which are the chars after the length of the base.
original = '/tmp/asd/asdqwe/file'
base = '/tmp/asd/'
if original.startswith(base):
wanted_part = original[len(base):]
print(wanted_part)
OUTPUT
asdqwe/file

How to use python to convert a backslash in to forward slash for naming the filepaths in windows OS?

I have a problem in converting all the back slashes into forward slashes using Python.
I tried using the os.sep function as well as the string.replace() function to accomplish my task. It wasn't 100% successful in doing that
import os
pathA = 'V:\Gowtham\2019\Python\DailyStandup.txt'
newpathA = pathA.replace(os.sep,'/')
print(newpathA)
Expected Output:
'V:/Gowtham/2019/Python/DailyStandup.txt'
Actual Output:
'V:/Gowtham\x819/Python/DailyStandup.txt'
I am not able to get why the number 2019 is converted in to x819. Could someone help me on this?
Your issue is already in pathA: if you print it out, you'll see that it already as this \x81 since \201 means a character defined by the octal number 201 which is 81 in hexadecimal (\x81). For more information, you can take a look at the definition of string literals.
The quick solution is to use raw strings (r'V:\....'). But you should take a look at the pathlib module.
Using the raw string leads to the correct answer for me.
import os
pathA = r'V:\Gowtham\2019\Python\DailyStandup.txt'
newpathA = pathA.replace(os.sep,'/')
print(newpathA)
OutPut:
V:/Gowtham/2019/Python/DailyStandup.txt
Try this, Using raw r'your-string' string format.
>>> import os
>>> pathA = r'V:\Gowtham\2019\Python\DailyStandup.txt' # raw string format
>>> newpathA = pathA.replace(os.sep,'/')
Output:
>>> print(newpathA)
V:/Gowtham/2019/Python/DailyStandup.txt

Double backslashes for filepath_or_buffer with pd.read_csv

Python 3.6, OS Windows 7
I am trying to read a .txt using pd.read_csv() using relative filepath. So, from pd.read_csv() API checked out that the filepath argument can be any valid string path.
So, in order to define the relative path I use pathlib module. I have defined the relative path as:
df_rel_path = pathlib.Path.cwd() / ("folder1") / ("folder2") / ("file.txt")
a = str(df_rel_path)
Finally, I just want to use it to feed pd.read_csv() as:
df = pd.read_csv(a, engine = "python", sep = "\s+")
However, I am just getting an error stating "No such file or directory: ..." showing double backslashes on the folder path.
I have tried to manually write the path on pd.read_csv() using a raw string, that is, using r"relative/path". However, I am still getting the same result, double backslashes. Is there something I am overlooking?
You can get what you want by using os module
df_rel_path = os.path.abspath(os.path.join(os.getcwd(), "folder1", "folder2"))
This way the os module will deal with the joining the path parts with the proper separator. You can omit os.path.abspath if you read a file that's within the same directory but I wrote it for the sake of completeness.
For more info, refer to this SO question: Find current directory and file's directory
You need a filename to call pd.read_csv. In the example 'a' is a only the path and does not point to a specific file. You could do something like this:
df_rel_path = pathlib.Path.cwd() / ("folder1") / ("folder2")
a = str(df_rel_path)
df = pd.read_csv(a+'/' +'filename.txt')
With the filename your code works for me (on Windows 10):
df_rel_path = pathlib.Path.cwd() / ("folder1") / ("folder2")/ ("file.txt")
a = str(df_rel_path)
df = pd.read_csv(a)

Resources