Python program needs full path in Notepad++ - python

Not a major issue but just an annoyance I've come upon while doing class work. I have my Notepad++ set up to run Python code straight from Notepad++ but I've noticed when trying to access files I have to use the full path to the file even given the source text file is in the same folder as the Python program being run.
However, when running my Python program through cmd I can just type in the specific file name sans the entire path.
Does anyone have a short answer as to why this might be or maybe how to reconfigure Notepad++?
Thanks in advance.

The problem is that your code is assuming that the current working directory is the same as the script directory. This is not true in general. Of course it is true if you're in a cmd window, and you cd to the script directory before running it.
If you don't want to rely on that (e.g., because you want to be able to run scripts from Notepad++, or directly from Explorer), what you want to do is use the script directory explicitly. For example:
import os
import sys
scriptdir = os.path.abspath(os.path.dirname(sys.argv[0]))
with open(os.path.join(scriptdir, 'myfile.txt')) as f:
# etc.
If you have a ton of files that your scripts reference in a ton of places, it might be better to explicitly set the working directory. Just add one line:
os.chdir(scriptdir)
For anything beyond quick&dirty scripts, it's usually better to build an installable package and use pkg_resources to access the data files. Read the Tutorial on Packaging and Distributing Projects for more details. But as long as you're only hacking up scripts to help you maintain your specific system, the scriptdir solution is workable.

In the properties of the shortcut that you use to start Notepad++, you can change its working directory, to whichever directory you're more accustomed to starting from in Python. You can also begin your python program with the appropriate os.chdir() command.

Related

How do programs know where their files are? And how to implement the same thing in python?

I am working on a python project that depends on some other files. It all works fine while testing. However, I want the program to run on start up. The working directory for programs that run on start up seems to be C:Windows\system32. When installing a program, it usually asks where to install it and no matter where you put it, if it runs on start up, it knows where its files are located. How do they achieve that? Also, how to achieve the same thing in python?
First of all, what do you mean by "their files"? Windows applications can store "their files" in multiple places (including but not limited to %CommonProgramFiles%, %ProgramData% and %AppData%).
That being said, the common location for simple applications and scripts is to use the same directory as the .exe (or script).
In Python there seems to be multiple ways to find this path, this seems to work nicely:
import os
print(os.path.abspath(os.path.dirname(__file__)))
See also:
How do I get the path of the Python script I am running in?
How do I get the path and name of the file that is currently executing?
If you plan to consume local files that contain raw data or processed data, defining a default directory or a set of directories can simplify your implementation, for example:
Place your data files under a specific set of folders in C:\ or place your files under the F:\ folder, that can be a part of your on premisses file system
Based on where your Python application is located, you'll need to use relative paths or a library to help you to locate these files.
Here are some examples:
os.path
pathlib

Run python script from another directory

I feel a little foolish that I don't know this, but I tried to do it today and was surprised when it didn't work....
I have a directory C:\test with a demo script, lets call it demo.py
If i am in C:\test then I can just do python demo.py. Easy
I could also use a relative path, so from C:\, it's python test\demo.py
What if C:\test is on the path?
I was expecting to be able to now do python demo.py from anywhere however...
python: can't open file 'demo.py': [Errno 2] No such file or directory
I feel foolish because I thought this was straightforward, but I have searched around and have not found a solution. Am I fundamentally misunderstanding something here about how the Python interpreter finds scripts to run? I don't think this is anything to do with PYTHONPATH, as I understood that to relate to loading of modules inside scripts.
This is on Windows 7, by the way.
The PATH is only used to search for commands. A first way is that a Python script can be used directly as a command and in that case the PATH will be used: just use demo.py instead of python demo.py.
It will rely on OS specific ways. On Windows, file type (given by the extension - here .py) can be given default application to process them, while on Unix-like, the first line of a script can declare the program that will process it.
Alternatively, python allows to launch a module that will be searched in the PYTHONPATH (not PATH) by using python -m module or for Windows py -m module.

When using Python Windows Launcher, is there any way to prevent having to type full path?

In Windows 8, I often use the Python Windows Launcher like
py C:/long/long/long/long/long/path/to/prog.py ...
Is there any way to set some environment setting, such as PATH or PYTHONPATH etc, to prevent having to type the full path to prog.py?
From my basic knowledge/research, PATH only helps with the py part of the command line and PYTHONPATH only helps with imports within prog.py, so how do I deal with the path to prog.py itself??
Notes:
I cannot modify the code, not even the "shebang" line, since it is needed to work on other platforms.
I cannot cd to the directory containing the programs to run them, because the programs will do something based on the directory they're run in (they'll modify the files in the directory they're run in).
I know that if I associate .py extension with the Python Windows Launcher, then I can run prog.py as the first item in the command line, and thus use PATH, but currently my .py extension is associated with my favorite editor and I'd like to keep it that way if possible (so I can double-click any Python file in Windows Explorer and edit it).
However, if someone suggests a solution where I can have a different association for Windows Explorer versus the command line, then that could be a potential solution! (i.e. in Windows Explorer, .py opens with the editor, while on command line, .py runs with Python Windows Launcher)
Add your long path to PYTHONPATH, then invoke your program as such:
python -m prog
Python will search for a module called prog and then run it as the main module.
Answer to my own question: Actually, I'm so silly. I could just set a variable for each program path (there are only a few programs paths), i.e.. prog=C:/long/path/to/prog.py and then do py %prog% .... I guess I figured out an answer to my own question that was acceptable to me.
Update: I just found something even better. I can do
doskey prog=py C:/long/path/to/prog.py $*
and then simply prog ... afterward
Now I just have to do some crazy stuff to get the doskey command into a file that will be run every time I start a console, as described here: https://stackoverflow.com/a/21040825/5182136

What scripts would go into a bin folder of a Python package?

I'm learning about Python Packages from Learn Python the Hard Way and one of the exercises it says:
Put a script in the bin directory that you can run
To me, it seems kind of vague. I'm not exactly sure what kind of scripts would go into the bin folder. The Hitchhiker's Guide to Packaging says
put into bin any scripts you’ve written that use your package and which you think would be useful for your users. If you don’t have any, then remove the bin directory.
But I'm still left wondering what kind of script would go in there. So, I know its may sound like a dumb question, but can someone give me an example of when, and why one would put "a script" in their package's bin folder?
I just recently got through Ex46 in LPTHW myself. Like you, I was confused by the scripts. In case the other answer was too advanced for you, I ended up just putting in a simple "hello world" script:
#!/usr/bin/env python
from test3 import printstring
printstring.printstring("test script working")
print "test over"
I named that file testscript3.py (*Note, I learned later that it would be more convenient to leave off the .py filename extension if it were a real script that I wanted to seem like a system command)
My file test3.py was like so:
def printstring(s='you did not provide string'):
print s
Here's some newbie things that I learned while trying to get this process to work:
The #! symbol is sometimes pronounced shebang and the simple explanation is that the command on that line tells the shell to use python to run the script. If you leave off the ".py" filename extension, then the user of the script doesn't need to care what interpreter is needed to run the script. See wikipedia shebang article.
I ran the following command to package the distribution:
python setup.py sdist
After doing that, I was able to install the package and script by running
sudo pip install test3-0.1.tar.gz
One thing I worried about was permissions on the script file. However, I noticed that distutils took care of this when packaging (changed mode to 755 or whatever).
You can find my whole project for this example on github.
For example Django's project creating, Scrapy's project creating, django-admin.py and scrapy are both scripts in bin folder.
You could get even more examples by checking almost python-based tools.

Best way to add script's working folder to import() path for Python on Windows?

I have a python program which I compile down to a Windows .exe using py2exe.
Using Inno Setup, I create a Windows installer.
The nature of my program is such that it uses plugins which are later imported using the __import__() statement. These plugins are located in a 'plugins' folder, which itself is located as a subfolder of where my program's .exe file resides.
Now, to have the program find the plugins, it earlier had the following statement somwhere at the top of my file:
sys.path+= ['.']
However, this was not working well when the user started the program through Windows' start menu, because apparently the working folder was set to the start menu (instead of where the .exe is located). So '.' did not resolve to what I wanted.
I fixed it by changing the statement to the following, so that the __import__() statement also looks in the folder where the .exe is located (because argv[0] is the full path of the executable):
sys.path+= [os.path.dirname(sys.argv[0])]
However, I am not sure if I picked the right solution. Especially, because my program is meant to be cross-platform (Windows, OSX, Linux) and the sys.argv documentation says about argv[0] that 'it is operating system dependent whether this is a full pathname or not'.
Should I solve this differently, or is my approach OK?
In my compiled to .exe Qt programms, I'm using code very similar to yours:
def executable_path():
self_file = unicode(sys.argv[0], sys.getfilesystemencoding())
return os.path.realpath(os.path.dirname(self_file))
I'm using unicode because path may contain non ascii symbols.
sys.argv[0] it is operating system dependent whether this is a full pathname or not
os.path.realpath solves that problem.
Why not have a config file with the path to the plugins dir? This lets the user move it, and you can have one for each os. Stick it with the executable, or maybe a couple well used locations, ~ or /etc on linux, and %homepath% on windows.
I often use this:
os.chdir(sys.argv[0].rsplit(os.sep, 1)[0])
that makes runtime consistent with development environment, where you run your script from it's directory.
Please use __file__ of the module. You can write like
sys.path+=os.path.dirname(mymodule.__file__)
This will add your module's parent directory in sys.path.

Categories