Why does QtWidgets.QApplication require sys.argv? - python-3.x

Hello guys i am learning pyqt5 from a series of tutorials at youtube and i didn't get why QtWidgets.QApplication have the argument sys.argv i am not familiar with sys library i read the documentation but still have no clue so sorry i know this question is kind of a noobish.
import sys
from PyQt5 import QtWidgets
def window():
app = QtWidgets.QApplication(sys.argv)
w=QtWidgets.QWidget()
w.show()
sys.exit(app.exec_())
window()

From the docs:
sys.argv
The list of command line arguments passed to a Python script. argv[0] is the script name (it is operating system dependent whether this is a full pathname or not). If the command was executed using the -c command line option to the interpreter, argv[0] is set to the string '-c'. If no script name was passed to the Python interpreter, argv[0] is the empty string.
To loop over the standard input, or the list of files given on the command line, see the fileinput module.
Example:
python foo.py
sys.argv = ['foo.py']
python foo.py bar baz
sys.argv = ['foo.py', 'bar', 'baz']
For your specific question, see this link: Why do I need "sys.argv" to start a QApplication in PyQt?
Basically, a QT application can take initialization arguments from the command line, the top answer should point you to a list of them with an explanation of what they do.

Related

How to run a python function from Windows 10 command prompt in 'python filename.py funcname' format?

I have the following python file, named hello.py:
print('Hello')
def world():
print('Hello World')
If I type the following within the command prompt for windows 10 I get:
In: python hello.py
Out: 'Hello'
In: python hello.py world
Out: 'Hello'
Notice in the second command prompt, 'Hello World' is not an output. Any reason on why my file can't execute the python function when called in the command line but is able to load the file no problem?
Why do I need this?: I need to submit a larger file that has many functions for a project. For this file to be automatically graded I need to be able to call any given function from it using the specific sequence 'python filename.py functionname.'
Update: Some of the answers below do work, but they do not follow the specific sequence of 'python filename.py functionname' required for my project to be graded. I appreciate the insights that everyone has provided so far.
You can run functions directly from the command prompt by using:
python -c 'from hello import world; world()'
You can run the python interpreter as an alternative. cd to your file directory and launch python:
python
and then import the function from your file:
from hello import world
(Launching the python cmd from the same directory as your file.)
Then, you can run:
>>> world()
Hello World
Try this piece of code and type hello.py only:
print('Hello')
def world():
return'Hello World'
world()
##################################################################
def F1():
print('This is the first function.')
if __name__ == '__main__':
F1()
def F2():
print('This is the second function.')
if __name__ == '__main__':
F2()
now you can use form(file_name) import(function_name) create folder(1) with multiple functions in it and you can try to import the desired function into another folder(2) one at a time not all of them all at once by using this.
pardon me for the mistakes if found any feel free to ask further if this does not elaborate.
I found a solution that works for me:
After digging deeper, I realized that windows passes a sys.argv input that contains a string of all the command prompt inputs used to call the file.
In my case of 'python hello.py world', the system would pass ['hello.py','world'] as the argument for sys.argv. By creating a dictionary of callable functions, and then matching the string of the sys.argv with its respective function in the dictionary, I am able to execute the code as desired.
New code:
print('Hello')
def world():
print('Hello World')
import sys
callable_functions = {'world':world}
callable_functions[sys.argv[1]]()
Command prompt input and output now:
In: python hello.py world
Out: 'Hello'
Out: 'Hello World'

Using sys.argv in Python 3 with Python interpreter

I’m trying to figure out how to use sys.argv in Python 3.6, but can’t figure out how to make it work using the Python interpreter (I’m not even 100% sure I’m actually using the interpreter, a bit confused around the terminology with interpreter, shell, terminal etc.)
Question 1: to access the Python interpreter, can I simply type $ python into the Terminal (I’m on a Mac)? If not, how do I access it?
Seems that when I go to find what I believe to be the interpreter in my files (I’ve downloaded Python via Anaconda), I find a program called “pythonw”, and starting this launches the Terminal, with what looks to be the Python interpreter already running. Is this the interpreter? The code chunk below is what is printed in a Terminal window when I run the "pythonw" program:
Last login: Tue Aug 7 18:26:37 on ttys001
Users-MacBook-Air:~ Username$ /anaconda3/bin/pythonw ; exit;
Python 3.6.5 |Anaconda, Inc.| (default, Mar 29 2018, 13:14:23)
[GCC 4.2.1 Compatible Clang 4.0.1 (tags/RELEASE_401/final)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>>
Question 2: Let’s assume that I have the Python interpreter running for the sake of argument. Assume also that I have the following script/module saved as test.py.
import sys
print('Number of arguments:', len(sys.argv), 'arguments.')
print('Argument List:', str(sys.argv))
If I simply import this module in the command line of the interpreter, I get the printout:
Number of arguments: 1 arguments.
Argument List: ['']
But how do I actually supply the module with arguments in the command line?
I've been looking around on internet, all of them showing this way of doing it, but it does not work.
Question 3: can the sys.argv only be used when arguments are written in the command line of the interpreter, or is there a way to supply a module with arguments in Spyder for instance?
Thank you for taking the time to read through it all, would make me so happy if I could get an answer to this! Been struggling for days now without being able to grasp it.
The Python interpreter is just a piece of code which translates and runs Python code. You can interact with it in different ways. The most straightforward is probably to put some Python code in a file, and pass that as the first argument to python:
bash$ cat <<\: >./myscript.py
from sys import argv
print(len(argv), argv[1:])
:
bash$ # in real life you would use an editor instead to create this file
bash$ python ./myscript.py one two three
4 ['one', 'two', 'three']
If you don't want to put the script in a file, perhaps because you just need to check something quickly, you can also pass Python a -c command-line option where the option argument is a string containing your Python code, and any non-option arguments are exposed to that code in sys.argv as before:
bash$ python -c 'from sys import argv; print(len(argv), argv[1:])' more like this
4 ['more', 'like', 'this']
(Single quotes probably make the most sense with Bash. Some other shells use other conventions to wrap a piece of longer text as a single string; in particular, Windows works differently.)
In both of these cases, the Python interpreter was started with a program to execute; it interpreted and executed that Python program, and then it quit. If you want to talk to Python more directly in an interactive Read-Eval-Print-Loop (which is commonly abbreviated REPL) that's what happens when you type just python:
bash$ python
Python 3.5.1 (default, Dec 26 2015, 18:08:53)
[GCC 4.2.1 Compatible Apple LLVM 7.0.2 (clang-700.1.81)] on darwin
Type "help", "copyright", "credits" or "license" for more information.
>>> 1+2
3
>>>
As you can see, anything you type at the >>> prompt gets read, evaluated, and printed, and Python loops back to the >>> to show that it's ready to do it again. (If you type something incomplete, the prompt changes to .... It will sometimes take a bit of puzzling to figure out what's missing - it could be indentation or a closing parenthesis to go with an opening parenthesis you typed on a previous line, for example.)
There is nothing per se which prevents you from assigning a value to sys.argv yourself:
>>> import sys
>>> sys.argv = ['ick', 'poo', 'ew']
At this point, you can import the script file you created above, and it will display the arguments after the first;
>>> import myscript
3, ['poo', 'ew']
You'll notice that the code ignores the first element of sys.argv which usually contains the name of the script itself (or -c if you used python -c '...').
... but the common way to talk to a module you import is to find its main function and call it with explicit parameters. So if you have a script otherscript.py and inspect its contents, it probably contains something like the following somewhere near the end:
def main():
import sys
return internal_something(*sys.argv[1:])
if __name__ == '__main__':
main()
and so you would probably instead simply
>>> import otherscript
>>> otherscript.internal_something('ick', 'poo')
Your very first script doesn't need to have this structure, but it's a common enough arrangement that you should get used to seeing it; and in fact, one of the reasons we do this is so that we can import code without having it start running immediately. The if __name__ == '__main__' condition specifically evaluates to False when you import the file which contains this code, so you can control how it behaves under import vs when you python myscript.py directly.
Returning to your question, let's still examine how to do this from a typical IDE.
An IDE usually shields you from these things, and simply allows you to edit a file and show what happens when the IDE runs the Python interpreter on the code in the file. Of course, behind the scenes, the IDE does something quite similar to python filename.py when you hit the Execute button (or however it presents this; a function key or menu item perhaps).
A way to simulate what we did above is to edit two files in the IDE. Given myscript.py from above, the second file could be called something like iderun.py and contain the same code we submitted to the REPL above.
import sys
sys.argv = ['easter egg!', 'ick', 'poo', 'ew']
import myscript

Pass arguments to jupyter notebook [duplicate]

I'm wondering if it's possible to populate sys.argv (or some other structure) with command line arguments in a jupyter/ipython notebook, similar to how it's done through a python script.
For instance, if I were to run a python script as follows:
python test.py False
Then sys.argv would contain the argument False. But if I run a jupyter notebook in a similar manner:
jupyter notebook test.ipynb False
Then the command line argument gets lost. Is there any way to access this argument from within the notebook itself?
After a lot of looking around I found very cumbersome, custom libraries, but solved it with a few lines of code which I thought was pretty slick. I used nbconvert to end up with an html report as output that contains all graphics and markdown from the notebook, but accepts command line parameters just as always through a minimal python wrapper:
The python file test_args.py (which takes command line params as normal):
import sys,os
IPYNB_FILENAME = 'test_argv.ipynb'
CONFIG_FILENAME = '.config_ipynb'
def main(argv):
with open(CONFIG_FILENAME,'w') as f:
f.write(' '.join(argv))
os.system('jupyter nbconvert --execute {:s} --to html'.format(IPYNB_FILENAME))
return None
if __name__ == '__main__':
main(sys.argv)
The notebook contains:
import sys,os,argparse
from IPython.display import HTML
CONFIG_FILE = '.config_ipynb'
if os.path.isfile(CONFIG_FILE):
with open(CONFIG_FILE) as f:
sys.argv = f.read().split()
else:
sys.argv = ['test_args.py', 'input_file', '--int_param', '12']
parser = argparse.ArgumentParser()
parser.add_argument("input_file",help="Input image, directory, or npy.")
parser.add_argument("--int_param", type=int, default=4, help="an optional integer parameter.")
args = parser.parse_args()
p = args.int_param
print(args.input_file,p)
and I can run the python notebook with arguments parsed as usual:
python test_args.py my_input_file --int_param 12
I tend to paste the block with argparse calls into the python wrapper so that command line errors are caught by the python script and -h works properly.
There are two projects I've found that do what you ask for
Papermill, will add a cell to your notebook with arguments that you pass to it on the command line. So this is quite straightforward, you define your defaults in the first cell (the should have parameters tag)
nbparameterise it is a similar concept but you don't tag your cell with defaults, it has to be first.
Here is a good resource discussing the issue: https://github.com/jupyter/help/issues/218
If the goal is to run a notebook with configurable arguments passed from commandline, I think the easiest way is to use environment variables, like this:
NB_ARGS=some_args jupyter nbconvert --execute --to html --template full some_notebook.ipynb
Then in the notebook, you can import os and use os.environ['NB_ARGS']. The variable value can be some text that contains key-value pairs or json for example.
At the top of the Jupyter cell, put a line like:
%%python - --option1 value1 --option2 value2 --etc
In your example:
%%python - True
This will run your script like in a command line with the args provided.
Example:
%%python - --option1 value1 --option2 value2 --etc
import sys
if __name__ == '__main__':
print(sys.argv)
will output:
['-', '--option1', 'value1', '--option2', 'value2', '--etc']
Hope it helps.
I think this Gist may help you : https://gist.github.com/gbishop/acf40b86a9bca2d571fa
This is an attempt at a simple argument parser for mostly key=value pairs that can be used both on the command line and in IPython notebooks. It support query parameters in notebook URLs and a Run command for notebooks.
Using args = parser.parse_args(args=[]) would work.
or for testing, you can declare it as class format.
class Args:
data = './data/penn'
model = 'LSTM'
emsize = 200
nhid = 200
args=Args()
sys.argv yields a list, so I used
sys.argv.append('hello')
in a jupyter notebook, which allowed me to append extra members and pretend like I'm passing in arguments from the command line.
I tried out the answers listed above, and came up with a different solution.
My original code was
ap = argparse.ArgumentParser()
ap.add_argument("-i", "--image", required=True, help="path to input image")
ap.add_argument("-y", "--yolo", required=True, help="base path to YOLO directory")
ap.add_argument("-c", "--confidence", type=float, default=0.5, help="minimum probability to filter weak detections")
ap.add_argument("-t", "--threshold", type=float, default=0.3, help="threshold when applying non-maxima suppression")
args = vars(ap.parse_args())
I tried to make a Class as
Class Args():
image='photo.jpg'
yolo='yolo-coco'
confidence=0.5
threshold=0.3
args=Args()
but futher code snippets were producing an error.
So I printed args after vars(ap.parse_args()) and found that it was a dictionary.
So just create a dictionary for the original args:
args={"image": 'photo.jpg', "yolo": 'yolo-coco', "confidence": 0.5,"threshold": 0.3}
A workaround is to make the jupyter notebook read the arguments from a file.
From the command line, modify the file and run the notebook.
I assume that you just want to parse some arguments to the notebooks, but it's not necessary to use the command line.
If you want to parse commands like.
python script.py --a A --b B
You can use the following code in the notebook:
cmd = '--a A --b B'
args = args = parser.parse_args(cmd)
For parse_args, you can find more information here.
A simple and naïve solution is to put the following snippet at the first line of your program:
import sys
sys.argv = "your expected command line arguments here".split()
After executing this command, packages like argparse will work well.
So, you can just run your scripts in the jupyter lab server, without opening a terminal and typing your arguments.

Can i access the variables of the python script after run that python script with console?

I run the python script using terminal command
python3 myScript.py
It's simply run my program but if i want to open python console after complete run of my script so that i can access my script's variables.
So, What should i do ? and How can i get my script's variables after run the code using terminal ?
Open a python terminal (type 'python' in cmd);
Paste this (replace 'myScript.py' with your script filename):
def run():
t = ""
with open('myScript.py') as f:
t = f.read()
return t
Type exec(run()). Now you will have access to the variables defined in myScript.py.
I needed to do this so I could explore the result of a request from the requests library, without having to paste the code to make the requests every time.
Make the program run the other program you want with the variables as arguments. For example:
#program1
var1=7
var2="hi"
import os
os.system("python %s %d %s" % (filename, var1, var2))
#program2
import sys
#do something such as:
print(sys.argv[1]) #for var1
print(sys.argv[2]) #for var2
Basically, you are running program2 with arguments that can be referenced later.
Hope this helps :)

Why does resizeColumnToContents work interactively at the python prompt, but not in a PyQt script?

I've been working on a filebrowser application, and I'd like the first column (file name) to be resized properly on startup. I can type the following code at the python prompt and the column resizes properly, but when I put it in a file and try to run it, the column is not resized. Any idea why?
#!/bin/env python
import sys
import os
from PyQt4.QtGui import *
app = QApplication(sys.argv)
treeView = QTreeView()
fileSystemModel = QFileSystemModel(treeView)
rootDir = fileSystemModel.setRootPath(os.path.expanduser('~'))
treeView.setModel(fileSystemModel)
treeView.setRootIndex(rootDir)
treeView.setGeometry(100,100,1024,768)
treeView.show()
treeView.resizeColumnToContents(0)
app.exec_()
Of course, when I copy it to the python prompt, I leave off the app.exec_(). Is that what is causing the column to not resize? (EDIT: I copied "app.exec_()" to the prompt and it did pretty much what you'd expect - the event loop started, and I was able to use the app, then close it, and then I was returned to the python prompt.)
It seems that replacing the call to treeView.resizeColumnToContents(0) with treeView.header().setResizeMode(0, QHeaderView.ResizeToContents) results in the column being expanded when run from the Python prompt and from a script. I have no clue why resizeColumnToContents is not working as intended.
Side note: should #!/bin/env python be #! /usr/bin/env python? At least on my distro, /bin/env doesn't exist.

Resources