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

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.

Related

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

Why does QtWidgets.QApplication require sys.argv?

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.

python 3 'input()' with textmate 2 'run'? [duplicate]

I wrote the following for a homework assignment and it works fine in IDLE and Eclipse running Python 3.
However, I tried to run it from TextMate with the new line 1 -- which I found here -- to point it to Python 3 on the Mac. It seems to be running Python 3 but returns an error. It says: EOFError: EOF when reading a line. It's referring to line 5 below.
Anyone know why?
BTW, this TextMate issue is not part of the homework assignment, so I'm not trying to get homework help. I just want to figure out how to use TextMate with Python 3.
#! /usr/local/bin/python3
#
# Tests user string against two conditions.
#
user_string = input("Enter a string that is all upper case and ends with a period: ")
if user_string.isupper() and user_string.endswith("."):
print("Your string met both conditions.")
else:
if user_string.isupper():
print("Your string does not end with a period.")
elif user_string.endswith("."):
print("Your string is not all upper.")
else:
print("Your string failed both conditions.")
The problem you are seeing has nothing to do with the Python version. The problem is that TextMate does not try to redirect standard input so, when you are running via the TextMate's Python bundle Run Script command, the Python program sees an immediate end-of-file. As explained here, TextMate used to be fancier about this but the mechanism it used no longer works in OS X 10.6 so the feature was disabled.
One solution is to use the Shift-Command-R Run Script in Terminal command of TextMate's Python bundle. This causes TextMate to open a terminal window and run the script there and you can enter the input there. Unfortunately, while TextMate does respect the shebang line with the normal Command-R Run Script command, it doesn't seem to do so with the Run Script in Terminal command. You can verify that yourself in various ways. Try running this code snippet in TextMate:
#! /usr/local/bin/python3
import sys
print(sys.executable)
To get around that, you can set the TM_PYTHON environment variable in TextMate. See the answer here for more details on how to do that.
Textmate is using the built-in Python, rather than respecting the shebang line. You'd probably have to hack the bundle code to use the right python.

How to convert Balsamiq mockups to text strings txt with Python34 script on Windows XP

I've been trying to run these scripts https://github.com/balsamiq/mockups-strings-extractor within XP. I'm getting errors per this screenshot https://www.dropbox.com/s/rlbqp1iytkwvq3m/Screenshot%202014-05-30%2011.57.48.png
Also I tried CD into my test directory and although a text output file is generated it is empty and I still get these errors https://www.dropbox.com/s/odjfbr97e5i4gnn/Screenshot%202014-05-30%2012.09.31.png
Is anybody running Balsamiq on windows able to make this work ?
1) From the looks of the first error pic you included, you were trying to execute a Windows Shell command inside of a Python Interpreter. If you've still got the window open, type quit() before attempting your command again.
2) Your script was written for Python 2.x. If you're using Python 3.x, you'll need to add parentheses to the print lines in the script file and change urllib to urllib.parse. I made the changes below:
import os
import glob
import re
import urllib.parse
for infile in glob.glob( os.path.join(".", '*.bmml') ):
print("STRINGS FOUND IN " + infile)
print("===========================================================")
f = open (infile,"r")
data = f.read()
p = re.compile("<text>(.*?)</text>")
textStrings = p.findall(data)
print(urllib.parse.unquote('\n'.join(textStrings))+"\n")
f.close()
Hope this helps.

Testing python programs without using python shell

I would like to easily test my python programs without constantly using the python shell since each time the program is modified you have to quit, re-enter the python shell and import the program again. I am using a 2012 Macbook pro with OSX. I have the following code:
import sys
def read_strings(filename):
with open(filename) as file:
return file.read().split('>')[1:0]
file1 = sys.argv[1]
filename = read_strings(file1)
Essentially I would like to read into and split a txt file containing:
id1>id2>id3>id4
I am entering this into my command line:
pal-nat184-102-127:python_stuff ceb$ python3 program.py string.txt
However when I try the sys.argv approach on the command line my program returns nothing. Is this a good approach to testing code, could anyone point me in the correct direction?
This is what I would like to happen:
pal-nat184-102-127:python_stuff ceb$ python3 program.py string.txt
['id1', 'id2', 'id3', 'id4']
Let's take this a piece at a time:
However when I try the sys.argv approach on the command line my
program returns nothing
The final result of your program is that it writes a string into the variable filename. It's a little strange to have a program "return" a value. Generally, you want a program to print it's something out or save something to a file. I'm guessing it would ease your debugging if you modified your program by adding,
print (filename)
at the end: you'd be able to see the result of your program.
could anyone point me in the correct direction?
One other debugging note: It can be useful to write your .py files so that they can be run both independently at the command line or in a python shell. How you've currently structured your code, this will work semi-poorly. (Starting a shell and then importing your file will cause an error because sys.argv[1] isn't defined.)
A solution to this is to change your the bottom section of your code as follows:
if __name__ == '__main__':
file1 = sys.argv[1]
filename = read_strings(file1)
The if guard at the top says, "If running as a standalone script, then run what's below me. If you imported me from some place else, then do not execute what's below me."
Feel free to follow up below if I misinterpreted your question.
You never do anything with the result of read_strings. Try:
print(read_strings(file1))

Resources