syntax error in AWS Greengrass V2 hello_world.py - python-3.x

I am experimenting with AWS IoT greengrass V2. I am just following the manual that has the following python code:
import sys
import datetime
message = f"Hello, {sys.argv[1]}! Current time: {str(datetime.datetime.now())}."
# Print the message to stdout.
print(message)
# Append the message to the log file.
with open('/tmp/Greengrass_HelloWorld.log', 'a') as f:
print(message, file=f)
According to my logging there is a syntax error in line 4. Replacing line 4 with the following works fine:
message = "Hello"
Does anyone see what is wrong with this line:
message = f"Hello, {sys.argv[1]}! Current time: {str(datetime.datetime.now())}."
Thanks.

I'm one of the documentation writers for AWS IoT Greengrass.
Formatted strings literals (f"some content") are a feature of Python 3.6+, and this syntax results in a syntax error in earlier versions. The getting started tutorial requirements incorrectly list Python 3.5 as a requirement, but Python 3.5 doesn't support formatted string literals. We'll update this requirement to say 3.6 or update the script to remove the formatted string literal.
To resolve this issue, you can upgrade to Python 3.6+ or modify the script to remove the formatted string literal. Thank you for finding this issue!

For the record: I altered the code, avoiding the f"stringliteral" :
import sys
import datetime
constrmessage ="Hello, ",str(sys.argv[1])," "+str(datetime.datetime.now())
#change from tuple to string
message = ''.join(constrmessage)
#print message to screen
print(message)
original_stdout = sys.stdout
# Append the message to the log file.
with open('/tmp/Greengrass_HelloWorld.log', 'a') as f:
sys.stdout = f
print(message)
sys.stdout = original_stdout

Related

How can I use python dictionary?

I already made json secret file like this.
json_data = {
'creon' :
{'token' : ["abcd"]}}
So I want to use exactly like this.
token = app_info['creon']['token']
print(token)
> "abcd"
But, result is like this.
print(token)
> abcd
How can I use the way I wanted?
Last tried result)
import os
import json
app_info = os.getenv('App_info')
with open(app_info, 'r') as f:
app_info = json.load(f)
token = '"'+app_info['creon']['token']+'"'
print(token)
TypeError: expected str, bytes or os.PathLike object, not NoneType
So I see couple of problems. First of all when you are doing it so, you are not getting a string values, but unicode {u'creon': {u'token': [u'abcd']}}, which can't work in you current situation. Now then you need to convert it to string when you get it like so app_info['creon']['token'][0].encode('utf-8').decode('utf-8') and then you can print it properly.
I modified the code to look like this:
import os
import json
app_info = os.getenv('App_info')
with open(app_info, 'r') as f:
app_info = json.load(f)
t = app_info['creon']['token'][0].encode('utf-8').decode('utf-8')
token = f'"{t}"'
print(token)
The second problem TypeError: expected str, bytes or os.PathLike object, not NoneType I think you get it because you haven't set environment variable to the path of your json data. I did it like so in my terminal export app_info=example.json and it worked properly when I executed the command python3 example.py with above python code in the same terminal session with exported environment variable.
If your question is how to print out the quotation marks along with the value, you can do:
print('"' + token + '"')

Getting 'positional argument' Error while sending a XML file to RabbitMQ from Python

I am trying to send a XML file to RabbitMQ from python but I am getting the below error
Error
File "<ipython-input-134-8a1b7f8b2e41>", line 3
channel.basic_publish(exchange='',queue='abc',''.join(lines))
^
SyntaxError: positional argument follows keyword argument
My Code
import ssl
!pip install pika
import pika
ssl_options = pika.SSLOptions(ssl._create_unverified_context())
credentials = pika.PlainCredentials(username='abcc', password='abcc')
connection = pika.BlockingConnection(pika.ConnectionParameters(
host='xxxx', port=5671, virtual_host ='xxx', credentials=credentials,
ssl_options=ssl_options))
channel = connection.channel()
result = channel.queue_declare(queue='abc')
with open('20200205280673.xml', 'r') as fp:
lines = fp.readlines()
channel.basic_publish(exchange='',queue='abc',''.join(lines))
Whats wrong in the above code?
As #ymz suggested, you are missing the body key in the basic.publish method. Also, the basic_publish method has no argument called queue. Please have a look at its implementation docs
Edit #1: I have already answered this question elsewhere How to send a XML file to RabbitMQ using Python?
Edit #2: Automating publishing of XML files. Assuming all the files are present in a directory called xml_files
import os
DIR = '/path/to/xml_files'
for filename in os.listdir(DIR):
filepath = f"{DIR}/{filename}"
with open(filepath) as fp:
lines = fp.readlines()
channel.basic_publish(exchange='exchange', routing_key='queue', body=''.join(lines))

Find the latest log file from multiple servers

For our daily monitoring we need to access 16 servers of a particular application and find the latest log file on one of those servers (it usually generates on the first 8).
The problem is that this code is giving me the latest file from each server instead of providing the latest log file from the entire group of servers.
Also, since this is an hourly activity, once the file is processed, it gets archived, so many of the servers don't have any log files present in them at a particular time. Due to this, while the below code is getting executed, I get - ValueError: max() arg is an empty sequence response and the code stops at server 3 if server 4 does not have any log files.
I tried adding default = 0 argument to latest_file but it gives me the error message TypeError: expected str, bytes or os.PathLike object, not int
Can you please help me out here? I am using Python 3.8 and PyCharm.
This is what I have so far :
import glob
import os
import re
paths = [r'\\Server1\Logs\*.log',
r'\\Server2\Logs\*.log',
.....
r'\\Server16\Logs\*.log']
for path in paths:
list_of_files = glob.glob(path)
latest_file = max(list_of_files, key=os.path.getctime)
f = open(os.path.join(latest_file), "r")
print(latest_file)
Create the list first and then find the max.
import glob
import os
import re
paths = [r'\\Server1\Logs\*.log',
r'\\Server2\Logs\*.log',
.....
r'\\Server16\Logs\*.log']
list_of_files = []
for path in paths:
list_of_files.extend(glob.glob(path))
if list_of_files:
latest_file = max(list_of_files, key=os.path.getctime)
f = open(os.path.join(latest_file), "r")
print(latest_file)
else:
print("No log files found!")

Python 3.5 not handling unicode input from CLI argument

I have a simple script that I'm attempting to use automate some of the japanese translation I do for my job.
import requests
import sys
import json
base_url = 'https://www.googleapis.com/language/translate/v2?key=CANT_SHARE_THAT&source=ja&target=en&q='
print(sys.argv[1])
base_url += sys.argv[1]
request = requests.get( base_url )
if request.status_code != 200:
print("Error on request")
print( json.loads(request.text)['data']['translations'][0]['translatedText'])
When the first argument is a string like 初期設定クリア this script will explode at line
print(sys.argv[1])
With the message:
line 5, in encode
return codecs.charmap_encode(input,self.errors,encoding_table)[0]
UnicodeEncodeError: 'charmap' codec can't encode characters in
position 0-6: character maps to <undefined>
So the bug can be reduced too
import sys
print(sys.argv[1])
Which seems like an encoding problem. I'm using Python 3.5.1, and the terminal is MINGW64 under Windows7 x64.
When I write the same program in Rust1.8 (and the executable is ran under same conditions, i.e.: MINGW64 under Windows7 x64)
use std::env;
fn main() {
let args: Vec<String> = env::args().skip(1).collect();
print!("First arg: {}", &args[0] );
}
It produces the proper output:
$ rustc unicode_example.rs
$ ./unicode_example.exe 初期設定クリア
First arg: 初期設定クリア
So I'm trying to understand what is happening here. MINGW64 claims to have proper UTF-8 support, which it appears too. Does Python3.5.1 not have full UTF-8 support? I was under the assumption the move to Python3.X was because of Unicode support.
changing
print(sys.argv[1])
to
print(sys.argv[1].encode("utf-8"))
Will cause python to dump a string of bytes
$ python google_translate.py 初期設定クリア
b'\xe5\x88\x9d\xe6\x9c\x9f\xe8\xa8\xad\xe5\xae\x9a\xe3\x82\xaf\xe3\x83
\xaa\xe3\x82\xa2'
Nonetheless it works. So the bug, if this is a bug... Is happening when python is decoding the internal string to print into the terminal, not when the argument is being encoded INTO a python string.
Also simply removing the print statement fixes the bug as well.

get console output

how can i receive the console output of any python file (errors, everything printed using the print() command)?
example:
main.py starts test.py and gets its output
You can use sys.stderr from the sys module. print() uses sys.stdout by default.
import sys
# Print to standard output stream
print("Normal output...")
# Print to standard error stream
print("Error output...", file=sys.stderr)
i dont know if this will help but im sure it will give you an idea.
in vb.net or c#.net we capture console stream using the process StandardOutput like this:
Dim p as Process = Process.Start("cmd")
p.WaitForExit(Integer.MaxValue)
dim output as String = p.StandardOutput

Resources