Call my Chat script from other Python script - python

This question is similar to other python from within python script calling but none of those are working for me.
I have a chat script which uses Python XMPP to send a chat message. The syntax is as so:
python chat.py -c "recipient#example.com" -u "sender#example.com" -p "secret" -m "message"
script:
#!/usr/bin/python
import sys
import argparse
import xmpp
def main(argv):
parser = argparse.ArgumentParser()
parser.add_argument('-c', dest='contact', required=True)
parser.add_argument('-u', dest='username', required=True)
parser.add_argument('-p', dest='password', required=True)
parser.add_argument('-m', dest='message', required=False, default='')
args = parser.parse_args(argv)
if (args.message == '') and not sys.stdin.isatty():
for line in sys.stdin:
args.message = args.message + line
jid = xmpp.protocol.JID(args.username)
jabber = xmpp.Client(jid.getDomain(), debug=[])
jabber.connect(server=(jid.getDomain(), 5222) )
jabber.auth(jid.getNode(), args.password)
jabber.send(xmpp.Message(args.contact, args.message.strip()))
if __name__ == "__main__":
main(sys.argv[1:])
as you can see, it takes 4 arguments.
Now I have another python script which is listening to sensors. I am trying to get it to send chat messages when it detects sensor readings so from within listen.py I am doing this:
...
import chat
...
chat.main('-c "chatto#server.com" -u "chatfrom#server.com" -p "password" -m "Yo Yo Yo Wassup"')
....
I have also tried subprocess.call but perhaps have not gotten the syntax correct. both python scripts are in the same directory. So for those of you looking for a specific question, How can I call the chat.py from within listen.py while providing the four required args?

parse_args() is going to expect a list of strings. For simple ones you can just split() on spaces, but in your case you have a complex argument with internal spaces so that won't work.
Don't include quotes in the strings. Those are used to allow an argument to have internal spaces when defined from the shell, but they aren't sent into argv.
chat.main(['-c', 'chatto#server.com', '-u', 'chatfrom#server.com', '-p', 'password', '-m', 'Yo Yo Yo Wassup'])
See more here: https://docs.python.org/2/library/argparse.html#beyond-sys-argv

Related

argparse error with parsing required arguments

I have a script saved as workspace.py
import argparse
import os
if __name__ == "__main__":
parser = argparse.ArgumentParser()
parser.add_argument('title', type=str, help="Will be displayed as the title")
parser.add_argument('-f', '--folder', help='Point to the folder you want to read from (defaults to current folder in command prompt)', type=str, default=os.getcwd())
args = parser.parse_args()
print(args)
someFunction(args.folder, args.title)
Which I call from terminal with:
workspace.py myTitle
Resulting in the error
workspace.py: error: the following arguments are required: title
I have no idea why this is happening because I supply "myTitle" in the terminal. If I specify a default= for the title argument it works perfectly with that value. The part that is throwing me is it doesn't even get to the print(args) so I cannot see what the program thinks is what, but instead fails at args = parser.parse_args()
I tried to even redo the exact example at: https://docs.python.org/2/howto/argparse.html#introducing-positional-arguments (copied below)
import argparse
parser = argparse.ArgumentParser()
parser.add_argument("echo", help="echo the string you use here")
args = parser.parse_args()
print args.echo
Running
workspace.py hello
Results in (after adding parenthesis to the print for 3.X)
workspace.py: error: the following arguments are required: echo
Is there something I'm missing? Why does it not just print "hello"? Is there some Python 3 specific syntax I'm missing or something?
I've gotten it to work if I run python workspace.py someString instead of workspace.py someString. I do not understand why this version works, since command prompt obviously recognizes it as Python and runs it correctly until args = parser.parse_args(). There were no errors like 'workspace.py' is not recognized as an internal or external command, operable program or batch file. There was no problem importing modules either. Consider the below command prompt session if you are running into a similar error. Maybe you will simply have to include python in your commands like I have to...
C:\Users\rparkhurst\PycharmProjects\Workspace>workspace.py MyTitle
usage: workspace.py [-h] [-f FOLDER] title
workspace.py: error: the following arguments are required: title
C:\Users\rparkhurst\PycharmProjects\Workspace>python workspace.py MyTitle
Namespace(folder='C:\\Users\\rparkhurst\\PycharmProjects\\Workspace', title='MyTitle')

how to handle input arguments that may be one value or a list of many?

I am working with a script from GitHub that someone wrote, which is designed for the command line. All the examples show something like:
thisscript.py -u 'teepee' -p pword999 -d 8
I want to run this inside another function, where I can use it like:
thisscript(username='teepee', password='pword999',...)
The main file includes a number of class definitions and this main function (below). What is the proper way to wrap this function such that I can call it as its own function?
if __name__ == '__main__':
parser = argparse.ArgumentParser(description='...', add_help=False, usage='thisscript.py -u username -p password [options]')
parser.add_argument('-u', metavar='<STR>', type=str, help='username')
parser.add_argument('-p', metavar='<STR>', type=str, help='password')
parser.add_argument('-a', metavar='<INT>', type=int, default=4, help='Number ascending [4]')
parser.add_argument('-d', metavar='<INT>', type=int, default=0, help='Number descending [0]')
I have tried doing import thisscript but that doesn't seem to work.
I think the simplest solution would be to call the script the way it was designed to be called -- in the shell -- by using the subprocess module.
import subprocess
def transcript(
username,
password,
descending_num=0,
ascending_num=4,
):
command = f'transcript.py -u {username} -p {password} -d {descending_num} -a {ascending_num}'
subprocess.call(command, shell=True)
Giving the function keyword arguments to mirror the script's default arguments is optional, but makes usage clearer.

Print any error from the script to a file - stderr

I have a python program that accepts three command line arguments -f (file1) -n (file2) -o (file3).
The program is structured as follows:
ffile=''
nfile=''
ofile=''
try:
myopts, args = getopt.getopt(sys.argv[1:],"f:n:o:h:")
for x,y in myopts:
if x == '-f':
ffile=y
elif x == '-n':
nfile=y
elif x == '-o':
ofile=y
<do something here with the files>
except:
sys.stderr("err.txt",w)
sys.exit(2)
What I am trying to do is:
If any of the arguments (-f,-n) are missing, then print a corresponding error.
Print the error message - whatever it might be - to a file "err.txt".
However, the err.txt file is empty. I am not sure what is going on. I have seen many questions where stderr is written to a file, but it does not seem to answer my question.
If you are open to changing your approach, I would recommend not trying to re-invent the wheel, and checking out some of the existing python libraries to accomplish this functionality.
There is a library called argparse that does well at parsing out command line arguments and returning appropriate error messages, maybe you would find it helpful.
import argparse
p = argparse.ArgumentParser(description='My Program', formatter_class=argparse.ArgumentDefaultsHelpFormatter)
p.add_argument("-f", type=str, help="-f file", required=True)
p.add_argument("-n", type=str, help="-n file", required=True)
p.add_argument("-o", type=str, help="-o file", default=None)
args = p.parse_args() # will throw error if required -f and -n args not passed
In terms of error logging, you could try using the python logging library. This library can be configured to log information to stdout, text files, etc. and is likely flexible enough for your requirements.

How to pass filepath as command line arugement in argparse python

I need to pass like
Python test.py -H host -U usr -P pass -L c:\newfolder\sample.sh -R /shell/sample.sh
I got error message too many values to unpack
Please help me to achieve this.
def check_argv(args=None)
parser = argparse.argumentParser()
parser.add_arugument('-H' , 'host')
#Same for all argument
#---------------------------------
Host, pass, user , local , remote = check_arg(sys.argv[1:])
You're probably getting the error because you are collecting less values than your function tuple is returning.That is in line.
And the correct way to use argparser function:
import argparse
parser = argparse.ArgumentParser()
parser.add_argument('-H', action="store", dest="host")
parser.add_argument('-U', action="store", dest="usr")
params = parser.parse_args()
And in your code you can get your parameters like this
# FETCHING ARGUMENT DETAILS
print(params.host, params.usr)
OUTPUT:
$python test.py -H hostname -U testuser
>>>hostname testuser
You can continue adding as many values as needed and get them back in the same way.

python script envoke -h or --help if no options are chosen

Trying to make my script more generic so I added some flags. My problem is the help only works if you type -h , obviously. I want to envoke -h when no flags are selected.
For example:
python 0_log_cleaner.py
Traceback (most recent call last):
File "0_log_cleaner.py", line 51, in <module>
getFiles(options.path,options.org_phrase,options.new_phrase,options.org_AN,options.new_AN,options.dst_path)
File "0_log_cleaner.py", line 37, in getFiles
for filename in os.listdir(path):
TypeError: coercing to Unicode: need string or buffer, NoneType found
but if I add -h I get:
python 0_log_cleaner.py -h
Usage: Example:
python 0_log_cleaner.py --sp original_logs/ --dp clean_logs/ --od CNAME --nd New_CNAME --oan 10208 --nan NewAN
Options:
-h, --help show this help message and exit
--sp=PATH Path to the source logs ie original_logs/
--dp=DST_PATH Path to where sanitized logs will be written to ie
clean_logs
--od=ORG_PHRASE original domain name ie www.clientName.com, use the command
-od clientName
--nd=NEW_PHRASE domain name to replace -od. ie -od clientName -nd domain
makes all log that use to be www.clientName.com into
www.domain.com
--oan=ORG_AN original AN number
--nan=NEW_AN AN number to replace original. ie -oan 12345 -nan AAAA1
replaces all instances of the AN number 12345 with AAAA1
EDIT 3 ANSWER
sample of my code to produce ^
import argparse
import sys
usage = "Description of function"
parser = argparse.ArgumentParser(description=usage)
parser.add_argument("--sp", dest="path", help='Path to the source logs ie logs/')
...
...(additional add arugments)
args = parser.parse_args()
def getFiles(path,org_phrase,new_phrase,org_AN,new_AN,dst_path):
if not len(sys.argv) > 1:
parser.print_help()
else:
run your logic
borrowed from here : Argparse: Check if any arguments have been passed
Here's how the final code looks like:
import argparse
import sys
usage = "Description of function"
parser = argparse.ArgumentParser(description=usage)
parser.add_argument("--sp", dest="path", help='Path to the source logs ie logs/')
...
...(additional add arugments)
args = parser.parse_args()
def getFiles(path,org_phrase,new_phrase,org_AN,new_AN,dst_path):
if not len(sys.argv) > 1:
parser.print_help()
else:
run your logic
If someone is still interested in a (very simple) solution:
parser = argparse.ArgumentParser()
parser.add_argument("jfile", type=str, help="Give the JSON file name.")
parser.add_argument("--output", type=str, help="Type in the final excel files name.")
try:
args = parser.parse_args()
return args
except:
parser.print_help()
My professor wanted the script to force the -h / --help page even when there are too few arguments. Instead of going like "python SCRIPT.py -h".
So what I did here was like: "Try to parse the arguments. And if it works, give them back to the main methode. Otherwise, if you fail (except), print the help(). Okay? Nice". ;)
Without knowing the method you are parsing with, I will assume the following (comment me if I am wrong or edit your question with some code on how you handle your parsing):
You are parsing everything and putting it in a variable. let parsed be that variable.
You are checking parsed for the existence of any of your option flags.
You probably not checking for the non-existence of arguments:
parsed = '' <- empty string
# or if you are using a list:
# parsed = []
if parsed: <- if parsed is not empty ("" or []) returns true
Do your stuff here, because you have options now
else: <- Differently options were not provided
Invoke the same method that you invoke when the option is -h
Also as #dhke suggests, consider using argparse if you are not using it already!
EDIT #1:
Translated for your specific case:
args = parser.parse_args() <-- ending line of your provided code
if not args:
parser.print_help()
else:
Do your stuff

Categories