Hi, I'm trying to use argparse in python as given code below, [duplicate] - python-3.x

Using argparse in a Jupyter Notebook throws a TypeError. The same code works fine if I execute the same code as a script. MWE:
import argparse
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')
args = parser.parse_args()
Result:
TypeError: 'level' is an invalid keyword argument for this function

One solution is to parse an empty list of arguments:
import argparse
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')
args = parser.parse_args([])
Another is to use parse_known_args:
args, _ = parser.parse_known_args()

Ipython is running some command-line arguments in the background. This interfers with argparse and optparse.
See this bug for Spyder (Ipython IDE), where -f was being added as a command option and crashing as there was no handler for -f.
You could try checking the arguments currently in play (as they did for the Spyder bug) and putting a dummy handler in place.
Run
import sys
print(sys.argv)
inside Ipython and see what it outputs.
On my system, it gives
['/usr/lib/python3.6/site-packages/ipykernel_launcher.py', '-f', '/run/user/1000/jupyter/kernel-7537e4dd-b5e2-407c-9d4c-7023575cfc7c.json']
Argparse assumes the first entry is the program name (sys.argv[0]). In order to fix this, I had to call
parser = argparse.ArgumentParser(prog='myprogram', description='Foo')
... and now argparse works in my notebook.

When I run your code in a Notebook, I get an argparse usage error message:
usage: ipykernel_launcher.py [-h] [--name NAME]
ipykernel_launcher.py: error: unrecognized arguments: -f /run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json
With a print(sys.argv) I get
['/home/paul/.local/lib/python3.6/site-packages/ipykernel_launcher.py', '-f', '/run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json']
sys.argv, which parser parses, contains the values used to launch the Notebook server, which this particular parser is not setup to handle.
parser.parse_known_args() displays:
(Namespace(name='foo'),
['-f',
'/run/user/1000/jupyter/kernel-a6504c0c-bed2-4405-8704-c008f52dcba6.json'])
That extra stuff that your parser can't handle is put in the extras list.
Run with a custom argv list works:
parser.parse_args(['-n', 'foobar'])
Namespace(name='foobar')
It's a good idea to put argparse code (at least the parse_args line) in a __main__ block, so it is not run when the script is imported. It will still run when the script is run as a script.
if __name__ == '__main__':
import argparse
parser = argparse.ArgumentParser(description='Foo')
parser.add_argument('--name', '-n', default='foo', help='foo')
args = parser.parse_args()
print(args)
This script also works when using %run stack50763033.py. You can even give it arguments as you would with a script:
%run stack50763033.py -n testing
I have no idea what code is producing the level keyword error. You'll have to give us the traceback if you want help with that.

Related

Python: subprocess + isql on windows: a bytes-like object is required, not 'str'

This is a company issued laptop and I can't install any new software on it. I can install Python modules to my own directory though. I need to run something on Sybase and there are 10+ servers. Manual operation is very time consuming hence I'm looking for the option as Python + subprocess.
I did some research and referred to using subprocess module in python to run isql command. However, my version doesn't work. The error message is TypeError: a bytes-like object is required, not 'str'. This error message popped up from the "communicate" line.
I can see my "isql" has connected successfully as I can get a isql.pid.
Anything I missed here?
Thank you
import subprocess
from subprocess import Popen, PIPE
import keyring
from textwrap import dedent
server = "MYDB"
cmd = r"C:\Sybase15\OCS-15_0\bin\isql.exe"
interface = r"C:\Sybase15\ini\sql.ini"
c = keyring.get_credential("db", None)
username = c.username
password = c.password
isql = Popen([cmd, '-I', interface,
'-S', server,
'-U', username,
'-P', password,
'-w', '99999'], stdin=PIPE, stdout=PIPE)
output = isql.communicate("""\
SET NOCOUNT ON
{}
go
""".format("select count(*) from syslogins"))[0]
From the communicate() documentation,
If streams were opened in text mode, input must be a string. Otherwise, it must be bytes.
By default, streams are opened in binary format, but you can change it to text mode by using the text=True argument in your Popen() call.

How to pass optionparser arguments through pylint?

test.py
from optparse import OptionParser
class Test(object):
def __init__(self):
pass
def _test1(self, some_val):
print(some_val)
def main(self, some_val):
self._test1(some_val)
if __name__ == "__main__":
parser = OptionParser()
parser.add_option("-a", "--abcd", dest="abcd", default=None,help="some_val")
(options, args) = parser.parse_args()
val = options.abcd
mainobj = Test()
mainobj.main(val)
Above script works, when executed python test.py --abcd=wxyz
When I run python -m pylint test.py --abcd=wxyz , doesn't execute.
Error:
strong text Usage: __main__.py [options]
__main__.py: error: no such option: --abcd
How to execute through pylint ?
Can you please help me ?
You cannot send new arguments like that using Pylint
Pylint is a static code analysis tool. It does NOT run your program. Therefore it does not matter what arguments are sent to the main program you want to test. Imagine it tests your code as it was "text" without running it.
Also the syntax you are using in the command line is not right, because after-m pylint the arguments which are sent are actually Pylint's arguments. Pylint has it's own set of options and rules you can set. you can view a summary here
or just type in your command line this:
pylint --help
The error message you get is a Pylint error. if you want to change the options you insert to Pylint you would have to change its source code i reckon...
Hope I understood your question correctly and that it helps.

I used Open CV to get the Image Difference using Python and code doesn't work

I am using Python 3.6.2. I am looking to run this code https://www.pyimagesearch.com/2017/06/19/image-difference-with-opencv-and-python/, but I have received this error:
usage: [-h] -f FIRST -s SECOND
error: the following arguments are required: -f/--first, -s/--second"
when I run the last line of this code and I don't know what is wrong:
from skimage.measure import compare_ssim
import argparse
import imutils
import cv2
import args
ap = argparse.ArgumentParser()
ap.add_argument("-f", "--first", required=True,default='I:\Aaron - Satslab\Pyimagesearch - code - Image processing and computer vision and others\image-difference\images\first.png',
help="firstinputimage")
ap.add_argument("-s", "--second", required=True,default='I:\Aaron - Satslab\Pyimagesearch - code - Image processing and computer vision and others\image-difference\images\second.png',
help="second")
args = vars(ap.parse_args())
Looking forward to your help.
The problem is that you added a default value to the arguments you add, but didn't set required=False. This means the program will throw an exception when parsing the arguments, unless you invoke it with the actual -f/--first and -s/--second.
The solution is to either:
Set required=False in both add_argument calls, since you provide a default. That way, you can call python my_script.py and it will use the default provided.
Invoke your program by providing the two CLI options: python my_script. py -f some_file.png -s some_other_file.png

python subprocess call from wsgi

When I run the exact same function from the python3 interpreter vs, apache via mod wsgi, they both run error free but one returns the command text from apache the stout is simply always blank. Again I am running the exact same function.
Backgorund, I want to run svn update on some code to do so I am using subprocess to simply call "svn update /path/to/repo"
def update():
p1=subprocess.Popen(["svn", "update", "/var/www/myrepocode"],stdout=subprocess.PIPE, stdin=subprocess.PIPE, stderr=subprocess.PIPE)
(ret, stderr) = p1.communicate(timeout=10)
return (str(ret.decode('utf-8')))
when i run from the python3 shell or another python 3 script called from the shell
from test import update
print(update())
it works fine and i get
"Updating '/var/www/myrepocode':\nAt revision 27.\n"
when I have a wsgi script and execute it from accessing the web page
def application(environ, start_response):
...
output = output + "---"+update() +"---"
...
response_headers = [('Content-type', 'text/html'), ('Content-Length',
str(len(output)))]
start_response(status, response_headers)
return [output.encode('utf-8')]
I get an empty string:
------
I do not have a python virtual environment, just normal python3 and there are no errors thrown either. I suspect this has to do with the user running it but I really don't know. setting shell=True doesn't change anything either. Any help is greatly appreciated.
Your update method does not return nor print stderr . Maybe you should check for errors first by adding the following line in the update method.
print(stderr)
If errors are produced, can you post them?

ipython notebook --script deprecated. How to replace with post save hook?

I have been using "ipython --script" to automatically save a .py file for each ipython notebook so I can use it to import classes into other notebooks. But this recenty stopped working, and I get the following error message:
`--script` is deprecated. You can trigger nbconvert via pre- or post-save hooks:
ContentsManager.pre_save_hook
FileContentsManager.post_save_hook
A post-save hook has been registered that calls:
ipython nbconvert --to script [notebook]
which behaves similarly to `--script`.
As I understand this I need to set up a post-save hook, but I do not understand how to do this. Can someone explain?
[UPDATED per comment by #mobius dumpling]
Find your config files:
Jupyter / ipython >= 4.0
jupyter --config-dir
ipython <4.0
ipython locate profile default
If you need a new config:
Jupyter / ipython >= 4.0
jupyter notebook --generate-config
ipython <4.0
ipython profile create
Within this directory, there will be a file called [jupyter | ipython]_notebook_config.py, put the following code from ipython's GitHub issues page in that file:
import os
from subprocess import check_call
c = get_config()
def post_save(model, os_path, contents_manager):
"""post-save hook for converting notebooks to .py scripts"""
if model['type'] != 'notebook':
return # only do this for notebooks
d, fname = os.path.split(os_path)
check_call(['ipython', 'nbconvert', '--to', 'script', fname], cwd=d)
c.FileContentsManager.post_save_hook = post_save
For Jupyter, replace ipython with jupyter in check_call.
Note that there's a corresponding 'pre-save' hook, and also that you can call any subprocess or run any arbitrary code there...if you want to do any thing fancy like checking some condition first, notifying API consumers, or adding a git commit for the saved script.
Cheers,
-t.
Here is another approach that doesn't invoke a new thread (with check_call). Add the following to jupyter_notebook_config.py as in Tristan's answer:
import io
import os
from notebook.utils import to_api_path
_script_exporter = None
def script_post_save(model, os_path, contents_manager, **kwargs):
"""convert notebooks to Python script after save with nbconvert
replaces `ipython notebook --script`
"""
from nbconvert.exporters.script import ScriptExporter
if model['type'] != 'notebook':
return
global _script_exporter
if _script_exporter is None:
_script_exporter = ScriptExporter(parent=contents_manager)
log = contents_manager.log
base, ext = os.path.splitext(os_path)
py_fname = base + '.py'
script, resources = _script_exporter.from_filename(os_path)
script_fname = base + resources.get('output_extension', '.txt')
log.info("Saving script /%s", to_api_path(script_fname, contents_manager.root_dir))
with io.open(script_fname, 'w', encoding='utf-8') as f:
f.write(script)
c.FileContentsManager.post_save_hook = script_post_save
Disclaimer: I'm pretty sure I got this from SO somwhere, but can't find it now. Putting it here so it's easier to find in future (:
I just encountered a problem where I didn't have rights to restart my Jupyter instance, and so the post-save hook I wanted couldn't be applied.
So, I extracted the key parts and could run this with python manual_post_save_hook.py:
from io import open
from re import sub
from os.path import splitext
from nbconvert.exporters.script import ScriptExporter
for nb_path in ['notebook1.ipynb', 'notebook2.ipynb']:
base, ext = splitext(nb_path)
script, resources = ScriptExporter().from_filename(nb_path)
# mine happen to all be in Python so I needn't bother with the full flexibility
script_fname = base + '.py'
with open(script_fname, 'w', encoding='utf-8') as f:
# remove 'In [ ]' commented lines peppered about
f.write(sub(r'[\n]{2}# In\[[0-9 ]+\]:\s+[\n]{2}', '\n', script))
You can add your own bells and whistles as you would with the standard post save hook, and the config is the correct way to proceed; sharing this for others who might end up in a similar pinch where they can't get the config edits to go into action.

Resources