Replacing characters in renaming - python

I am trying to do a simple Maya renaming UI but I am stuck at a part - replacing he initial characters in the current naming with other characters
For example; 3 items in the Outliner(irregardless of what they are):- pCube1, - pSphere1, - nurbsSphere1
So far I am able to write up to the point where it can selects and rename 1 or more objects, see code below
objects = []
objects = cmds.ls(sl=True)
for obj in objects:
test = []
test = cmds.rename(obj, "pSphere" )
print objects
# Results: pSphere, pSphere2, pSphere3 #
However, suppose now I am selecting nurbsSphere1 and pSphere1, and I just wanted to replace the word 'Sphere' in them with 'Circle', instead of getting the results as: nurbsCircle1, pCircle1, I got a error message # TypeError: Too many objects or values. #
charReplace = "test"
if charReplace in objects:
newName = []
newName = cmds.rename(objects, "Circle" )
Any advices on it?

As per the documentation rename command takes only strings as input parameters. You are providing a list named objects while trying to rename the filenames.
Moreover, you are searching for string "test" in objects list.
Instead you should search for string "test" in each filename which is present in objects list.
rename command renames the old string with the newer one. It does not replace the substring within a string (e.g. "sphere" in "nurbsSphere"). In order to achieve this you should create the new filenames separately and then use them to rename the files.
You can try this:
charReplace = "test"
for filename in objects:
if charReplace in filename:
newFilename = filename.replace(charReplace, "Circle")
cmds.rename(filename, newFilename)
I do not have Maya installed so code is not tested.

Related

Is there a way to "transform" a CSV table into a simple nested if... else block in python?

I'm fairly new to python and I'm looking forward to achieve the following:
I have a table with several conditions as in the image below (maximum 5 conditions) along with various attributes. Each condition comes from a specific set of values, for example Condition 1 has 2 possible values, Condition 2 has 4 possible values, Condition 3 has 2 possible values etc..
What I would like to do: From the example table above, I would like to generate a simple python code so that when I execute my function and import a CSV file containing the table above, I should get the following output saved as a *.py file:
def myFunction(Attribute, Condition):
if Attribute1 & Condition1:
myValue = val_11
if Attribute1 & Condition2:
myValue = val_12
...
...
if Attribute5 & Condition4:
myValue = val_54
NOTE: Each CSV file will contain only one sheet and the titles for the columns do not change.
UPDATE, NOTE#2: Both "Attribute" and "Condition" are string values, so simple string comparisons would suffice.
Is there a simple way to do this? I dove into NLP and realized that it is not possible (at least from what I found in the literature). I'm open to all forms of suggestions/answers.
You can't really use "If"s and "else"s, since, if I understand your question correctly, you want to be able to read the conditions, attributes and values from a CSV file. Using "If"s and "else"s, you would only be able to check a fixed range of conditions and attributes defined in your code. What I would do, is to write a parser (piece of code, which reads the contents of your CSV file and saves it in another, more usable form).
In this case, the parser is the parseCSVFile() function. Instead of the ifs and elses comparing attributes and conditions, you now use the attributes and conditions to access a specific element in a dictionary (similar to an array or list, but you can now use for example string keys instead of the numerical indexes). I used a dictionary containing a dictionary at each position to split the CSV contents into their rows and columns. Since I used dictionaries, you can now use the strings of the Attributes and Conditions to access your values instead of doing lots of comparisons.
#Output Dictionary
ParsedDict = dict()
#This is either ';' or ',' depending on your operating system or you can open a CSV file with notepad for example to check which character is used
CSVSeparator = ';'
def parseCSVFile(filePath):
global ParsedDict
f = open(filePath)
fileLines = f.readlines()
f.close()
#Extract the conditions
ConditionsArray = (fileLines[0].split(CSVSeparator))[1:]
for x in range(len(fileLines)-1):
#Remove unwanted characters such as newline characters
line = fileLines[1 + x].strip()
#Split by the CSV separation character
LineContents = line.split(CSVSeparator)
ConditionsDict = dict()
for y in range(len(ConditionsArray)):
ConditionsDict.update({ConditionsArray[y]: LineContents[1 + y]})
ParsedDict.update({LineContents[0]: ConditionsDict})
def myFunction(Attribute, Condition):
myValue = ParsedDict[Attribute][Condition]
The "[1:]" is to ignore the contents in the first column (empty field at the top left and the "Attribute x" fields) when reading either the conditions or the values
Use the parseCSVFile() function to extract the information from the csv file
and the myFunction() to get the value you want

Calling existing variable (list) reconstructed with StringVar()

I have a several lists that I am trying to activate or use that are named as follows:
public_forum_jr_soc = []
parliamentary_jr_soc = []
european_jr_soc = []
etc...
I have a bunch of radiobuttons that has variables to recreate these lists names, and it outputs something like this.
print(self.select_league.get()+self.select_age.get()+self.select_grade.get())
append_name = self.select_league.get()+self.select_age.get()+self.select_grade.get()
>>>
european_jr_soc
I try to proceed to use this list in as an argument for a function.
output_data(append_name)
def master_groper2(outof48):
for i in outof48:
if i[15] in ['ENGLISH','english','']:
i[15] = 'English'
elif i[15] in ['Mandarin','CHINESE',]:
i[15] = 'Chinese'
However, I get a IndexError: string index out of range as python reads it as european_jr_soc, instead of the actual list, despite sharing the same name, how could I have python have it read it as the variable list?

concatenation of string & integer NAMES within functions (python3)

This is the first posting I've done to this forum.
I have these strings, integers, and filenames declared early on...
linefeed='\n'
consonantFileHeader='Consonants found in the infile:'
vowelFileHeader='Vowels found in the infile:'
qConsonant=0
qVowel=0
ConsonantFile=open(path/tothe/file/chapters/Consonants.txt,'w+')
VowelFile=open(path/tothe/file/chapters/Vowels.txt,'w+')
the program reads in unicode glyphs one by one, and assigns each a 'type'.
if glyph='A':
type='VOWEL'
elif glyph='B':
type='CONSONANT'
... etc...
later on, we want to add to a running count of each 'type' and write a record to a file that shows all the occurrences of each 'type'. It's routine code, that we don't want cluttering up our main function, so we call another function to do it....
if type == 'CONSONANT':
tabulateCONSONANT(glyph)
elif type == 'VOWEL':
tabulateVOWEL(glyph)
at this point, two different types - two different functions. here they are...
## ------------------------------------------------------------
def tabulateCONSONANT(glyph):
qConsonant=qConsonant+1 # bump up a counter
if qConsonant = 1 # on 1 write header to output
ConsonantFile.write(consonantFileHeader)
ConsonantFile.write(glyph+linefeed) # write data after
return ;
## ------------------------------------------------------------
def tabulateVOWEL(glyph):
qVowel=qVowel+1 # bump up counter
if qVowel = 1
VowelFile.write(vowelFileHeader) # on 1, write header
VowelFile.write(glyph+linefeed) # write data after
return ;
fine and dandy, but this seems really redundant to me. even though only the actual NAMES of the values change, I have to call a different function for each type!
Is there any way write a single function that wherein we can concatenate the actual ITEM NAMES to do something like the following...?
if type == 'CONSONANT':
tabulateANYTHING(glyph,'Consonant')
elif type == 'VOWEL':
tabulateANYTHING(glyph,'Vowel')
## ------------------------------------------------------------
def tabulateANYTHING(glyph,TYPE):
# concatenate 'q'with 'TYPE' to reference 'qVowel'
qTYPE=qTYPE+1
if qTYPE = 1
# concatenate 'TYPE' with part of the filename > 'VowelFile'
TYPEFile.write(TYPEFileHeader)
TYPEFile.write(glyph+linefeed) # again,concatenation...
return ;
if you don't know what the heck I'm trying to do here, let me know and I'll try to make it clearer...
Create a dict or a collections.Counter and then inside tabulateANYTHING increment the value that has the key that matches TYPE
For example, if your dict is named quantities:
quantities[TYPE]+=1
For the files, create a dict of files and write to the one that has the key that matches TYPE.
Same thing for the file headers.

Rename multiple images randomly from a list of keywords using python 2.7

I am trying to rename multiple images using os.rename() in Python from a
list keyword_name randomly so I break it into these steps:
def keyword()
keyword_name a list that holds keyword
loop through list
assign a variable that holds the index(list[])
import os
keyword_name = "key.jpg","alph.jpg","hold.jpg","name.jpg","kid.jpg",
"young","zolo","lima0","sofia","temra","tooad","aeder","ed","de","cf","fc"
def keyword():
index = 0
while index < len(keyword_name):
keyword = keyword_name[index]
print(keyword)
index += 1
def rename_name()
returns a list containing the names of the entries in the directory given by path.
returns current working directory of a process.
def renam_name():
file_list = os.listdir(r"C:\Desktop\cLine\file")
saved_path =os.getcwd()
os.chdir(r"C:\Desktop\cLine\file")
for f in file_list:
#spilt text to file_name,img_type
file_name, img_type = os.path.splitext(f)
#convert the tuple to a list
keyword = list(file_name)
#join the list
name = "".join(keyword)
print(name)
os.rename(name, keyword_name)
I am new to programming. I did some research, but I only found how to remove integers or a string from file_name. I'll be so thankful if somebody can help me.
The sources I've been looking at:
Rename multiple files in a directory in Python
Rename multiple files in Python
There are many parts of your code that aren't needed.
The keyword method should randomly select a keyword from keyword_name.
Then, call it to provide the 2nd argument to os.rename.
Try this (I placed comments inline):
import os
import random
# Use a list instead of a tuple so that we can modify
keyword_name = ["key","alph","hold","name","kid", "young","zolo","lima0","sofia","temra","tooad","aeder","ed","de","cf","fc"]
def keyword():
# Generate a random index
rand_index = random.randint(0, len(keyword_name)-1)
# Get the keyword
rand_keyword = keyword_name[rand_index]
# Remove the used-up keyword from the list to
# prevent randomly selecting it again when renaming
keyword_name.remove(rand_keyword)
return rand_keyword
def renam_name():
os.chdir(r"<path-to-image-folder>")
file_list = os.listdir(r"<path-to-image-folder>")
for f in file_list:
# get the file extension
file_name, img_type = os.path.splitext(f)
# Call the random keyword generator then use the return
# value as the new file name.
os.rename(f, keyword() + img_type)
renam_name()
In addition, since keywords are chosen at random, you'll have to prevent selecting the same keyword, so that the code will not rename the file to a previously renamed file. To do this, I remove the already-chosen keyword from keyword_name (I needed to change keyword_name to a list because tuples are immutable).
It might be also better to remove the ".jpg" extensions from the keyword_name list, as those will produce new filenames like "name.jpg.png".

Conditional copying of files in python

so I'm trying to copy files to another directory if their filename starts with the same 4 digit ID as the values my list.
I'm either getting the wrong data written to the file or nothing at all.
What I have so far:
import shutil
import os
ok_ids = [5252,
8396,
8397,
8397,
8556,
8004,
6545,
6541,
4392,
4392,
6548,
1363,
1363,
1363,
8489,
8652,
1368,
1368]
source = os.listdir("/Users/amm/Desktop/mypath1/")
destination = "/Users/amm/Desktop/mypath2/"
for files in source:
for x in ok_ids:
if files[:4] == x:
shutil.copy(files,destination)
else:
print("not working")
Sample of the files I'm trying to copy i.e. source
0000_051123_192805.txt
0000_051123_192805.txt
8642_060201_113220.txt
8652_060204_152839.txt
8652_060204_152839.txt
309-_060202_112353.txt
x104_051203_064013.txt
destination directory is blank
A few important things: ok_ids does not contain distinct values, but i'd like the the program to treat the list as if it does contain distinct values. for example 8397 appears in the ok_ids list twice and it doesnt need to be iterated over twice in the ok_ids loop (its a verrry long list and i dont fancy editing). source can often contain duplicate id's also, using the example above these are 0000, 8652, but the rest of the filename is different.
So in summary... if 0000 is in my ok_ids list and there are filenames beginning with 0000 in my source directory then i want to copy them into my destination folder.
I've looked at using .startswith but its not happy using a list as the argument even if i cast it to a tuple and then a str. Any help would be amazing.
UPDATE
Could the reason for this not working be that some of the ids contain a hyphen? and others start with a char x not a int value?
The first 4 values are the ID, for example these are still valid:
309-_060202_112353.txt
x104_051203_064013.txt
This should work:
for file in source:
for x in set(ok_ids):
if file.startswith(str(x)):
shutil.copy(file, destination)
Use set() to make numbers unique and str() to convert to string. So you can preprocess the list into a set for better performance.
Or better yet, given your naming constraints:
if int(file.split("_")[0]) in ok_ids:
Why your code doesn't work?
if files[:4] == x:
You're comparing a str with a int, which, intuitively, will always be False.
import os
import shutil
for root, dirs, files in os.walk("/Users/amm/Desktop/mypath1/"):
for file in files:
try:
if int(file[:4]) in ok_ids:
shutil.copy(file,destination)
except:
pass
This worked for me. The only catch is that it crawls all folders in the same directory.
Your code works for me with the slight modification of str(x) instead of x.
Try using this to see what it is doing with each file:
for files in source:
for x in ok_ids:
if files[:4] == str(x):
print("File '{}' matched".format(files))
break
else:
print("File '{}' not matched".format(files))
Or, alternatively, convert all the items in ok_ids to strings and then see what this produces:
ok_ids = [str(id) for id in ok_ids]
files_matched = [file for file in source if file[:4] in ok_ids]
files[:4] == x can never be true because x is an integer and files[:4] is a string. It does not matter if the string representation of x matches:
>>> 123 == '123'
False
I've looked at using .startswith but its not happy using a list as the argument even if i cast it to a tuple and then a str. Any help would be amazing.
This is arguably the best way to solve the problem, but you don't just need a tuple - you need the individual ID values to be strings. There is no possible "cast" (they are not really casts) you can perform on ok_ids that affects the elements.
The simplest way to do that is to make a tuple in the first place, and have the elements of the tuple be strings in the first place:
ok_ids = (
'5252',
'8396',
# ...
'1368'
)
If you do not control this data, you can use a generator expression passed to tuple to create the tuple:
ok_ids = tuple(str(x) for x in ok_ids)

Categories