Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 9 years ago.
Improve this question
I'm current working through Learning Python the Hard Way, and it is perhaps going a little fast for me. I've input the following code, with along with the corresponding file. In the py file, I wrote:
#!/usr/bin/python
from sys import argv
script, filename = argv
txt = open(filename)
print "Here's your file %r:" % filename
print txt.read()
print "Type the filename again:"
file_again = raw_input("> ")
txt_again = open(file_again)
print txt_again.read()
And to run it, I wrote: python script.py readme.txt which ran the code.
However, I don't quite understand the process here:
How come #!/usr/bin/python must be at the top of the file
What is sys import argv
What is script, filename = argv
Is .read() a built in function?
#!/usr/bin/python is the so-called Shebang, a hint to the OS kernel that it is a Python script which should be executed with the given Python binary. Thus, if you chmod +x the script, you can even call it with ./script.py readme.txt.
from sys import argv is a command to import argv from the sys module directly into our namespace. So we can use argv to access it instead of sys.argv. If we only use it once, it may be better to just import sys and access everything inside via e.g. sys.argv. You'll find about that in the Python docs and/or tutorial.
script, filename = argv is a shorthand for
script = argv[0]
filename = argv[1]
as long as argv contains exactly 2 elements. You'll find about that in the Python docs and/or tutorial.
file.read() is indeed built-in, but as a file object method, not as a function as such.
The #!/usr/bin/python will turn your python script into an executable, a special unix trick. The executable scripts usually start with a line that begins with thecharacters #! (“hash bang”), followed by the path to the Python interpreter on your machine. Then by changing the mode to +x of that particular script file, you will be able to execute it on the prompt by just calling the name. As this path may be different for different machines, you can use the unix "env" workaround:
#!/usr/bin/env python
This will allow the env program to locate the python interpreter and execute the code
From modulename import something is used to import a module, but we are only importing "argv" attribute from the module sys. From is just like import, but does a bit more work for you where it copies the module's attribute (argv) in this case, so that they become simple variables in the recipient script.
script, filename = argv will simply assign argv[0] and argv[1] to script and filename respectively.
And finally, file.read is a builtin method for file objects.
Answers:
1) #!/usr/bin/python is there for UNIX users, it shows python where to find certain files. (Why do people write #!/usr/bin/env python on the first line of a Python script?)
2) sys import argv is the file in the argument [readme.txt] (http://www.tutorialspoint.com/python/python_command_line_arguments.htm)
3) script, filename = argv Script and Filename [new variables] take on the value from argv.
4) Yes, .read() is a built in function. (http://www.diveintopython.net/file_handling/file_objects.html)
Google is your friend on this one...
1) Unix-like convention. It allows to determine what to do with the file as soon as the first line of file is read.
2) from sys import argv means import only argv from the module named sys
3) a,b = 1,2 assigns 1 to a, and 2 to b. If there is an _iterable_ object on the RHS then such constructs are equivalent:
script, filename = argv
===
script = argv[0]
filename = argv[1]
4) Yes. Maybe not built-in strictly speaking - it's just a function provided in one of Python's standard input output module.
Related
I have 4 python script files.
script_1.py
script_2.py
script_3.py
script_4.py
script_1.py, script_2.py and script_3.py calls script_4.py
Execute files always change.
Like, python script_1.py / python script_2.py / python script_3.py
I want to get script_1.py, script_2.py, and script_3.py file name in script_4.py python script.
How can I get current executing file name without having to pass that information as arguments?
I tried __name__ and inspect.getfile(inspect.currentframe()) but no luck.
Both of codes are returns script_4.py.
When called, sys.argv holds the command line arguments. The first element is the name of the script that was called (including path). To get the name of the script that was originally called you can do, in any of your files:
import os
import sys
called_script_with_path = sys.argv[0]
called_script_without_path = os.path.basename(sys.argv[0])
You can use the module level attribute __file__ to get the path to the current module.
>>> import os
>>> os.path.basename(__file__)
test.py
If you want to determine this for another file, you can import the script and still query the value:
>>> import os
>>> import script1
>>> os.path.basename(script1.__file__)
script1.py
Closed. This question is opinion-based. It is not currently accepting answers.
Want to improve this question? Update the question so it can be answered with facts and citations by editing this post.
Closed 10 months ago.
The community reviewed whether to reopen this question 10 months ago and left it closed:
Original close reason(s) were not resolved
Improve this question
I have a script named test1.py which is not in a module. It just has code that should execute when the script itself is run. There are no functions, classes, methods, etc. I have another script which runs as a service. I want to call test1.py from the script running as a service.
For example:
File test1.py:
print "I am a test"
print "see! I do nothing productive."
File service.py:
# Lots of stuff here
test1.py # do whatever is in test1.py
I'm aware of one method which is opening the file, reading the contents, and basically evaluating it. I'm assuming there's a better way of doing this. Or at least I hope so.
The usual way to do this is something like the following.
test1.py
def some_func():
print 'in test 1, unproductive'
if __name__ == '__main__':
# test1.py executed as script
# do something
some_func()
service.py
import test1
def service_func():
print 'service func'
if __name__ == '__main__':
# service.py executed as script
# do something
service_func()
test1.some_func()
This is possible in Python 2 using
execfile("test2.py")
See the documentation for the handling of namespaces, if important in your case.
In Python 3, this is possible using (thanks to #fantastory)
exec(open("test2.py").read())
However, you should consider using a different approach; your idea (from what I can see) doesn't look very clean.
Another way:
File test1.py:
print "test1.py"
File service.py:
import subprocess
subprocess.call("test1.py", shell=True)
The advantage to this method is that you don't have to edit an existing Python script to put all its code into a subroutine.
Documentation: Python 2, Python 3
import os
os.system("python myOtherScript.py arg1 arg2 arg3")
Using os you can make calls directly to your terminal. If you want to be even more specific you can concatenate your input string with local variables, ie.
command = 'python myOtherScript.py ' + sys.argv[1] + ' ' + sys.argv[2]
os.system(command)
If you want test1.py to remain executable with the same functionality as when it's called inside service.py, then do something like:
test1.py
def main():
print "I am a test"
print "see! I do nothing productive."
if __name__ == "__main__":
main()
service.py
import test1
# lots of stuff here
test1.main() # do whatever is in test1.py
I prefer runpy:
#!/usr/bin/env python
# coding: utf-8
import runpy
runpy.run_path(path_name='script-01.py')
runpy.run_path(path_name='script-02.py')
runpy.run_path(path_name='script-03.py')
You should not be doing this. Instead, do:
test1.py:
def print_test():
print "I am a test"
print "see! I do nothing productive."
service.py
#near the top
from test1 import print_test
#lots of stuff here
print_test()
Use import test1 for the 1st use - it will execute the script. For later invocations, treat the script as an imported module, and call the reload(test1) method.
When reload(module) is executed:
Python modules’ code is recompiled and the module-level code reexecuted, defining a new set of objects which are bound to names in the module’s dictionary. The init function of extension modules is not called
A simple check of sys.modules can be used to invoke the appropriate action. To keep referring to the script name as a string ('test1'), use the 'import()' builtin.
import sys
if sys.modules.has_key['test1']:
reload(sys.modules['test1'])
else:
__import__('test1')
As it's already mentioned, runpy is a nice way to run other scripts or modules from current script.
By the way, it's quite common for a tracer or debugger to do this, and under such circumstances methods like importing the file directly or running the file in a subprocess usually do not work.
It also needs attention to use exec to run the code. You have to provide proper run_globals to avoid import error or some other issues. Refer to runpy._run_code for details.
Why not just import test1? Every python script is a module. A better way would be to have a function e.g. main/run in test1.py, import test1 and run test1.main(). Or you can execute test1.py as a subprocess.
I found runpy standard library most convenient. Why? You have to consider case when error raised in test1.py script, and with runpy you are able to handle this in service.py code. Both traceback text (to write error in log file for future investigation) and error object (to handle error depends on its type): when with subprocess library I wasn't able to promote error object from test1.py to service.py, only traceback output.
Also, comparing to "import test1.py as a module" solution, runpy is better cause you have no need to wrap code of test1.py into def main(): function.
Piece of code as example, with traceback module to catch last error text:
import traceback
import runpy #https://www.tutorialspoint.com/locating-and-executing-python-modules-runpy
from datetime import datetime
try:
runpy.run_path("./E4P_PPP_2.py")
except Exception as e:
print("Error occurred during execution at " + str(datetime.now().date()) + " {}".format(datetime.now().time()))
print(traceback.format_exc())
print(e)
This process is somewhat un-orthodox, but would work across all python versions,
Suppose you want to execute a script named 'recommend.py' inside an 'if' condition, then use,
if condition:
import recommend
The technique is different, but works!
Add this to your python script.
import os
os.system("exec /path/to/another/script")
This executes that command as if it were typed into the shell.
An example to do it using subprocess.
from subprocess import run
import sys
run([sys.executable, 'fullpathofyourfile.py'])
This is an example with subprocess library:
import subprocess
python_version = '3'
path_to_run = './'
py_name = '__main__.py'
# args = [f"python{python_version}", f"{path_to_run}{py_name}"] # works in python3
args = ["python{}".format(python_version), "{}{}".format(path_to_run, py_name)]
res = subprocess.Popen(args, stdout=subprocess.PIPE)
output, error_ = res.communicate()
if not error_:
print(output)
else:
print(error_)
According to the given example, this is the best way:
# test1.py
def foo():
print("hellow")
# test2.py
from test1 import foo # might be different if in different folder.
foo()
But according to the title, using os.startfile("path") is the best way as its small and it works. This would execute the file specified. My python version is 3.x +.
I have script1, in there the String "path" gets set. Then the script1 runs blender as a subprocess, together with script2.
Now script2 needs to have access to the String "path", how can I do this?
Currently im Saving the string to a text file and then accesing it from script2 but I know this solution is very very ugly.
maybe someone has an idea ? :)
script1:
path=("/example/ex/")
subprocess.run([blenderpath, "--background", blenderscene, "--python", scriptpath])
script2 (atm just reading out the txt file with the right path, but that's not how I want it to be):
file=open("Blabla")
file_name = fiel.readline()
mat_path = file_name
def prepscene(mat_path)
It works right now with the text file, but If I try to import the variable into the second script it won't work, if I try to somehow start the blender script with it it also won't work.
import sys # to get command line args
argv = sys.argv
argv will be array
If you just want to access the varible you can use importing.
ScriptA:
...
path = "/example/ex/"
...
ScriptB:
from .ScriptA import path
(this only works if both scripts are in the same directory)
This question already has answers here:
How do I get the path and name of the file that is currently executing?
(26 answers)
Closed 7 years ago.
I have a python script that accepts file names as arguments and performs operation on those files. Currently the script is in the same directory as the files it operates on. But I want to be able to run my python script from anywhere in the operating system. When I give the file name as argument to the script, it should know exactly which directory to look for regardless of where the python script is running in the system. How can I achieve this in python?
Here is the relevant portion of the script. Can I just hard code the path?
The type_mapping_file will be the filename passed into the script as an argument.
data = None
with open (type_mapping_file, "r") as myfile:
data=myfile.read()
if(data is not None):
request_params = {'type': type_name, 'index': index_name}
send_http_request("/index/type/create", request_params, base_url, post_body=data)
Thank you in advance.
how should it know that?
if it's a constant path you could hardcode it into the script and use os.path to build the full path:
import os
import sys
BASE_PATH = '/my/const/path'
fullpath = os.path.join(BASE_PATH,sys.argv[1])
although, as stated in comments, a more flexible solution would be to pass the path as a separate argument, or pass absolute path for each file
I assume you're looking for a way to find the path that's given via a relative path, perhaps calling the script itself from another location.
$ cat print_path.py
import os
import sys
print os.path.abspath(sys.argv[1])
If you call this script on a relative path, it prints the absolute path, so you can find it on the disk. The magic is from os.path.abspath().
$ python print_path.py ./planning.md
/Users/Gijs/Desktop/planning.md
$ cd ..
Also if you're calling from somewhere else.
$ python Desktop/print_path.py Desktop/planning.md
/Users/Gijs/Desktop/planning.md
Edit
No, wait, you're looking for the location of the python file that's executing. That's in __file__, see How do I get the path and name of the file that is currently executing?.
The full path to the current file is a magic variable called __file__. This is a suitable argument to functions like os.path.dirname():
print("This Python file is in " + os.path.dirname(__file__))
You can then os.path.join() this with the argument supplied on the command line to get files in the same directory as the script, wherever that may be.
Note that using __file__ in this fashion is not ideal for reusable packages. It is preferred to use pkgutil.get_data() or the equivalent Setuptools function. Basically, you pass it a module or package name (typically __name__, the name of the current module, or __package__, the name of the package you're in) and it retrieves the files for you. This is required if your module is going into an importable zip file or somewhere else where __file__ doesn't exist or have a useful value.
Is there a universal approach in Python, to find out the path to the file that is currently executing?
Failing approaches
path = os.path.abspath(os.path.dirname(sys.argv[0]))
This does not work if you are running from another Python script in another directory, for example by using execfile in 2.x.
path = os.path.abspath(os.path.dirname(__file__))
I found that this doesn't work in the following cases:
py2exe doesn't have a __file__ attribute, although there is a workaround
When the code is run from IDLE using execute(), in which case there is no __file__ attribute
On Mac OS X v10.6 (Snow Leopard), I get NameError: global name '__file__' is not defined
Test case
Directory tree
C:.
| a.py
\---subdir
b.py
Content of a.py
#! /usr/bin/env python
import os, sys
print "a.py: sys.argv[0]=", sys.argv[0]
print "a.py: __file__=", __file__
print "a.py: os.getcwd()=", os.getcwd()
print
execfile("subdir/b.py")
Content of subdir/b.py
#! /usr/bin/env python
import os, sys
print "b.py: sys.argv[0]=", sys.argv[0]
print "b.py: __file__=", __file__
print "b.py: os.getcwd()=", os.getcwd()
print
Output of python a.py (on Windows)
a.py: __file__= a.py
a.py: os.getcwd()= C:\zzz
b.py: sys.argv[0]= a.py
b.py: __file__= a.py
b.py: os.getcwd()= C:\zzz
Related (but these answers are incomplete)
Find path to currently running file
Path to current file depends on how I execute the program
How can I know the path of the running script in Python?
Change directory to the directory of a Python script
First, you need to import from inspect and os
from inspect import getsourcefile
from os.path import abspath
Next, wherever you want to find the source file from you just use
abspath(getsourcefile(lambda:0))
You can't directly determine the location of the main script being executed. After all, sometimes the script didn't come from a file at all. For example, it could come from the interactive interpreter or dynamically generated code stored only in memory.
However, you can reliably determine the location of a module, since modules are always loaded from a file. If you create a module with the following code and put it in the same directory as your main script, then the main script can import the module and use that to locate itself.
some_path/module_locator.py:
def we_are_frozen():
# All of the modules are built-in to the interpreter, e.g., by py2exe
return hasattr(sys, "frozen")
def module_path():
encoding = sys.getfilesystemencoding()
if we_are_frozen():
return os.path.dirname(unicode(sys.executable, encoding))
return os.path.dirname(unicode(__file__, encoding))
some_path/main.py:
import module_locator
my_path = module_locator.module_path()
If you have several main scripts in different directories, you may need more than one copy of module_locator.
Of course, if your main script is loaded by some other tool that doesn't let you import modules that are co-located with your script, then you're out of luck. In cases like that, the information you're after simply doesn't exist anywhere in your program. Your best bet would be to file a bug with the authors of the tool.
This solution is robust even in executables:
import inspect, os.path
filename = inspect.getframeinfo(inspect.currentframe()).filename
path = os.path.dirname(os.path.abspath(filename))
I was running into a similar problem, and I think this might solve the problem:
def module_path(local_function):
''' returns the module path without the use of __file__. Requires a function defined
locally in the module.
from http://stackoverflow.com/questions/729583/getting-file-path-of-imported-module'''
return os.path.abspath(inspect.getsourcefile(local_function))
It works for regular scripts and in IDLE. All I can say is try it out for others!
My typical usage:
from toolbox import module_path
def main():
pass # Do stuff
global __modpath__
__modpath__ = module_path(main)
Now I use _modpath_ instead of _file_.
You have simply called:
path = os.path.abspath(os.path.dirname(sys.argv[0]))
instead of:
path = os.path.dirname(os.path.abspath(sys.argv[0]))
abspath() gives you the absolute path of sys.argv[0] (the filename your code is in) and dirname() returns the directory path without the filename.
The short answer is that there is no guaranteed way to get the information you want, however there are heuristics that work almost always in practice. You might look at How do I find the location of the executable in C?. It discusses the problem from a C point of view, but the proposed solutions are easily transcribed into Python.
See my answer to the question Importing modules from parent folder for related information, including why my answer doesn't use the unreliable __file__ variable. This simple solution should be cross-compatible with different operating systems as the modules os and inspect come as part of Python.
First, you need to import parts of the inspect and os modules.
from inspect import getsourcefile
from os.path import abspath
Next, use the following line anywhere else it's needed in your Python code:
abspath(getsourcefile(lambda:0))
How it works:
From the built-in module os (description below), the abspath tool is imported.
OS routines for Mac, NT, or Posix depending on what system we're on.
Then getsourcefile (description below) is imported from the built-in module inspect.
Get useful information from live Python objects.
abspath(path) returns the absolute/full version of a file path
getsourcefile(lambda:0) somehow gets the internal source file of the lambda function object, so returns '<pyshell#nn>' in the Python shell or returns the file path of the Python code currently being executed.
Using abspath on the result of getsourcefile(lambda:0) should make sure that the file path generated is the full file path of the Python file.
This explained solution was originally based on code from the answer at How do I get the path of the current executed file in Python?.
This should do the trick in a cross-platform way (so long as you're not using the interpreter or something):
import os, sys
non_symbolic=os.path.realpath(sys.argv[0])
program_filepath=os.path.join(sys.path[0], os.path.basename(non_symbolic))
sys.path[0] is the directory that your calling script is in (the first place it looks for modules to be used by that script). We can take the name of the file itself off the end of sys.argv[0] (which is what I did with os.path.basename). os.path.join just sticks them together in a cross-platform way. os.path.realpath just makes sure if we get any symbolic links with different names than the script itself that we still get the real name of the script.
I don't have a Mac; so, I haven't tested this on one. Please let me know if it works, as it seems it should. I tested this in Linux (Xubuntu) with Python 3.4. Note that many solutions for this problem don't work on Macs (since I've heard that __file__ is not present on Macs).
Note that if your script is a symbolic link, it will give you the path of the file it links to (and not the path of the symbolic link).
You can use Path from the pathlib module:
from pathlib import Path
# ...
Path(__file__)
You can use call to parent to go further in the path:
Path(__file__).parent
Simply add the following:
from sys import *
path_to_current_file = sys.argv[0]
print(path_to_current_file)
Or:
from sys import *
print(sys.argv[0])
If the code is coming from a file, you can get its full name
sys._getframe().f_code.co_filename
You can also retrieve the function name as f_code.co_name
The main idea is, somebody will run your python code, but you need to get the folder nearest the python file.
My solution is:
import os
print(os.path.dirname(os.path.abspath(__file__)))
With
os.path.dirname(os.path.abspath(__file__))
You can use it with to save photos, output files, ...etc
import os
current_file_path=os.path.dirname(os.path.realpath('__file__'))