How to pass newline characters in MEL variables to Python - python

I have tested the following code. It works fine.
string $testString = "test";
python("exec(\'with open(\\\'C:/Users/username/Desktop/testString.txt\\\', \\\'w\\\') as f:\\n\t\f.write(\\\'"+$testString+"\\\')\')");
Similarly, I can use Python to write a variable that contains a newline character, as shown below.
testString = "test\ntest\n"
with open('C:/Users/username/Desktop/testString.txt', 'w') as f:
f.write(testString)
However, when I tested the following code, I got an error.
string $testString = "test\ntest\n";
python("exec(\'with open(\\\'C:/Users/username/Desktop/testString.txt\\\', \\\'w\\\') as f:\\n\t\f.write(\\\'"+$testString+"\\\')\')");
error message is below:
# Error: line 2: EOL while scanning string literal #
I want to use a combination of MEL and Python to output a multi-line string to a text file. If possible, I would like to achieve this by changing only the python code, without changing the contents of the MEL variables.
How can I do this?
My environment is Maya2020 + Python2.
However, I get the exact same error with Maya2022 + Python3.

You need to escape the "\" symbol in your string several times (for MEL, for Python and for exec):
string $testString = "test\\\\ntest\\\\n";
python("exec(\'with open(\\\'C:/Users/username/Desktop/testString.txt\\\', \\\'w\\\') as f:\\n\t\f.write(\\\'"+$testString+"\\\')\')");
Or if you wish to leave your string intact use encodeString:
string $testString = "test\ntest\n";
python("exec(\'with open(\\\'C:/Users/username/Desktop/testString.txt\\\', \\\'w\\\') as f:\\n\t\f.write(\\\'"+ encodeString(encodeString($testString)) + "\\\')\')");
By the way, you don't need to use exec. This way you'll simplify the escaping quite a lot:
string $testString = "some test\ntest\n";
python("with open('C:/Users/username/Desktop/testString.txt', 'w') as f:\n\tf.write('"+ encodeString($testString) + "')");
Another option would be using MEL for file output:
string $testString = "test\ntest\n";
$file_id = `fopen "C:/Users/username/Desktop/testString.txt" "w"`;
fprint $file_id $testString;
fclose $file_id;

Related

How do I split a string with backward slashes in from the backward slashes substring using split() of python?

I have a string which looks similar to 123456 \\RE1NUM=987 and I have been trying to split it \\RE1NUM=.
I have tried .split("\\RE1NUM=") and it gives ['123456 \\', '987']. I believe backward slashes are being interpreted as escape characters.
The final list I need will be ['123456 ', '987'].
The "string" is actually a line I am reading from a file object. It does work when isolated and tested on string, but fails when used on file's line. (I'll try to recreate this problem on a test file and paste the contents here.)
Can you try to use a different editor? cause I have tried to use the python shell in my terminal and it did indeed give me the desired output as follows
replit link: https://replit.com/#shivvohra/StackOverflow1?v=1
Code:
string = '123456 \\RE1NUM=987'
var = string.replace("\\", " ").split()
first_six_letters = var[0]
last_few_numbers = var[1].split('=')
last_three_letters = last_few_numbers.pop(1)
combined = [first_six_letters, last_three_letters]
print(combined)
Output:
['123456', '987']
enter image description here
for example code:
string = "123456 \\RE1NUM=987"
result = string.split("\\\\RE1NUM=")
print(result)

How do I get python to interpret the ANSI escape codes for colors in a string read from a text file

All the codes I've tried work in VS Code terminal and the Widows Terminal (Power Script and Command Window), so I'm pretty happy about that, however, when I read a string from a text file and I print the string, the escape codes are printed in plain view and no colour is applied to the strings.
I've tried the octal, hexadecimal and unicode versions, I had the same problem with "\n" until I realised that the string read would contain "\n", where it would effectively escape the "" char, so calling .replace("\\n","\n") on the string solved that issue, but I got no joy with the colour codes.
This is the code that I use to read the file:
with open('ascii_art_with_color.txt','r') as file:
for line in file.readlines() :
text_line = line
print( text_line , end='' )
Sample from the ascii file:
encounter = You \033[31mencounter\033[0m a wolf howling at the moonlight
Printing using the print function works just fine, either the string constant or from a variable
print('The wolf \033[31mgrowls\033[0m at you as you try to get closer')
winning = 'The wolf lets out a \033[34mpiercing\033[0m cry, then falls to the ground'
print(winning)
Ideas? The main problem that got me stumped is that the codes are not interpreted/applied for the strings I read from the text file, anything else seems to work.
Update:
As it was suggested in the comments, the file contained the '\033' (4 chars) instead of the '\033' one char. I was hoping python would take the line, then apply/translate/encode it into the ANSI escape sequence code while printing it, as it does with the string in the example above.
In the meantime, I managed to get the colours in the text file using a script that replaces a specific string with the escape sequence (I guess python does the encoding behind the scenes before writing it to file)
file_dest = 'ascii_monster_wolf_dest.txt'
with open(file_name,'r') as file, open(file_dest,'w+') as file_dest:
for line in file.readlines():
line = line.replace('{#}','\033[31m')
line = line.replace('{*}','\033[0m')
file_dest.writelines(line)
This is some progress, but not what I really wanted tho.
Coming back to my question, is there a way to read the file and have the sequence '\033' (4 characters) being interpreted as the 1 char escape sequence, the way it seems to do with strings?
There are a couple of ways to do what you ask.
If you wrap the individual lines with quote marks, so they look like Python string constants, you can use the ast literal evaluator to decode it:
s = '"\\x61\\x62"'
# That string has 10 characters.
print( ast.literal_eval(s) )
# Prints ab
Alternatively, you can convert the strings to byte strings, and use the "unicode-escape" codec:
s = '\\x61\\x62'
s = s.encode('utf-8').decode('unicode-escape')
print( s )
# Prints ab
In my humble opinion, however, you would be better served by using some other kind of markup to denote your colors. By that, I mean something like:
<red>This is red</red> <blue>This is blue</blue
Maybe not exactly an HTML-type syntax, but something with code markers that YOU understand, that can be read by humans, and can be interpreted by all languages.
Open the file in binary format. Then use decode() as Tim Roberts suggested.
with open('ascii_art_with_color.txt','rb') as file:
for line in file.readlines() :
print( line.decode('unicode-escape') , end='' )

I want to print the "\" character in python but I get "\\"

I have a python list of strings with 000_S_0000 formatting. Since I want this list to be displayed in a LaTeX document, I want to save it first in a .txt file using a different formatting for each of its strings, specifically this one: 000\_S\_0000.
However, when I wrote the modified list in the .txt file, each string was formated as 000\\_S\\_0000 instead.
How could I solve that? Why isn't it working?
Thanks in advance!
This is my code:
def posa_barres_latex(ll_PTIDs):
for i in range(len(ll_PTIDs)):
snou = ''
for caracter in ll_PTIDs[i]:
if caracter == "_":
snou = snou + "\_"
else:
snou = snou + caracter
ll_PTIDs[i] = snou
with open("sortida_exclosos_criteri_c.txt","w") as f:
f.write(str(ll_PTIDs))
posa_barres_latex(['002_S_2043', '018_S_2138', '013_S_2324', '129_S_4073', '002_S_4237', '019_S_4285', '130_S_4468', '136_S_4517', '013_S_4791', '031_S_4194','002_S_4219', '002_S_4251', '136_S_4408', '130_S_4605', '130_S_4925', '013_S_4985'])
P.S. I am using python 3.
To print a single '\' using the print command just use:
print('\\')
The first '\' escapes the second one.
Your Python version matters in this case.
But '\' is the escape character, it's used to encode other characters, for example '\n' is a newline.
You can escape '\' as \\ and it'll just print '\'.
If you're using strings with a lot of them, it might be easier to use raw strings - just put an r in front of them. Example:
print(r"000\_S\_000")
Will print it exactly as you type it.

Python script to duplicate .tex files with small changes

I have a letter in LaTeX format. I'd like to write a short script in python that takes one argument (the addressee) and creates a .tex file with the general letter format and the addressee.
from sys import argv
script, addressee = argv
file = open('newletter.tex', 'w')
file.write("\begin{Document} Dear " + addressee + ", \n Greetings, how are you? Sincerely, Me \end{Document}")
file.close()
Is there a better function to write out large blocks of text? Also, you can see that the .tex file will contain programming syntax - will python disregard this as long as it is coerced to a string? Do I need to coerce a large block to string? Thanks in advance!
If you directly enter print "\begin..." into your interpreter, you will notice the result will omit the \b on the front of the string. This is because \b is a character that the print statement (or function if you're in 3.x) recognizes (it happens to be a backspace).
To avoid this confusion, you can use a "raw string", which in python is denoted by pre-pending an 'r':
>>> a = "\begin"
>>> b = r"\begin"
>>> print a
egin
>>> print b
\begin
>>>
Typically, when working with strings to represent file paths, or anything else which may contain a \ character, you should use a raw string.
As far as inserting information into a template, I would recommend using the format() function rather than string concatenation. To do this, your string would look like this:
r"\begin{{Document}} Dear {} \n Greetings, how are you? Sincerely, Me \end{{Document}}".format(addressee)
The argument of the function (in this case addressee) will be inserted into each {} within the string. For this reason, curly brackets which should be interpreted literally must be escaped by included them in duplicate.
I'd take the approach of creating the tex files first as letter.tex with the addressee set to something like QXQ_ADDRESSEE_QXQ.
The in the python script I'd read the entire file into memory. When you read from a file, it gets treated as a raw string with proper escaping.
with open('letter.tex', 'r') as f:
raw_letter = f.readlines()
Then just do a substitution and write the string to a file.
raw_letter.replace("QXQ_ADDRESSEE_QXQ", newname)
with open('newletter.tex', 'w') as f:
f.write(raw_letter)

How to escape string so it can be parsed as Python code to give original string?

When generating Python code by a Python script, there is a string in s from which a line of Python code should be generated with the behavior of t = '...', with generation by:
code_t_assign = "t = '{}'".format(s)
The initial s can for example be '\", where proper escaping should then make code like:
t = '\'\\"'
What is the safe way to escape special characters like \ and ' in s to the code line for assign of t can execute?
Based on comment from #LukasGraf:
code_t_assign = "t = {}".format(repr(s))
Resulting in code as:
t = '\'\\"'

Categories