Python Best Practice. Call commandline python file from another python file - python

I retrieved a python project from some git repo. To run this project, there is a file that must be launched by command line with the correct arguments. Here is an example :
#! /usr/bin/env python
import argparse
parser = argparse.ArgumentParser(description='Description')
parser.add_argument('arg1')
parser.add_argument('arg2')
# %%
def _main(args):
# Execute the code using args
if __name__ == '__main__':
_main(parser.parse_args())
I want to use this code in my own project, and so, call the main function from another python file, using a set of predefined arguments.
I have found different ways of doing so, but I don't know what is the good way to do it.
Calling the file using the os package, but seems like a bad practice to me.
Refactoring the file so that the main function take the wanted parameters (and getting rid of args object), but it means that command line call would not work anymore.
Other ?

Import otherprogram into your own program.
Call otherprogram._main() from the appropriate point in your own code, passing it an argparse.Namespace instance.
You can build that using your own argparse calls if you need to, or just construct the values some other way.

You can actually call the main method as long as you make sure args contain the object with the correct attributes. Consider this
import argparse
def _main(args):
print(args.arg1)
_main(argparse.Namespace(arg1='test1', arg2='test2'))
In another file you can do this:
from some_git_repo import _main
from argparse import Namespace
_main(Namespace(arg1='test1', arg2='test2'))

Related

How should I organize my scripts which are mostly the same?

So I'm new to Python and I need some help on how to improve my life. I learned Python for work and need to cut my workload a little. I have three different scripts which I run around 5 copies of at the same time all the time, they read XML data and add in information etc... However, when I make a change to a script I have to change the 5 other files too, which is annoying after a while. I can't just run the same script 5 times because each file needs some different parameters which I store as variables at the start in every script (different filepaths...).
But I'm sure theres a much better way out there?
A very small example:
script1.py
xml.open('c:\file1.xls')
while True:
do script...
script2.py
xml.open('c:\file2.xls')
while True:
do exactley the same script...
etc...
You'll want to learn about Python functions and modules.
A function is the solution to your problem: it bundles some functionality and allows you to call it to run it, with only minor differences passed as a parameter:
def do_something_with_my_sheet(name):
xml.open(name)
while True:
do script...
Elsewhere in your script, you can just call the function:
do_something_with_my_sheet('c:\file1.xls')
Now, if you want to use the same function from multiple other scripts, you can put the function in a module and import it from both scripts. For example:
This is my_module.py:
def do_something_with_my_sheet(name):
xml.open(name)
while True:
do script...
This is script1.py:
import my_module
my_module.do_something_with_my_sheet('c:\file1.xls')
And this could be script2.py (showing a different style of import):
from my_module import do_something_with_my_sheet
do_something_with_my_sheet('c:\file2.xls')
Note that the examples above assume you have everything sitting in a single folder, all the scripts in one place. You can separate stuff for easier reuse by putting your module in a package, but that's beyond the scope of this answer - look into it if you're curious.
You only need one script, that takes the name of the file as an argument:
import sys
xml.open(sys.argv[1])
while True:
do script...
Then run the script. Other variables can be passed as additional arguments, accessed via sys.argv[2], etc.
If there are many such parameters, it may be easier to save them in a configuration file, the pass the name of the configuration file as the single argument. Your script would then parse the file for all the information it needs.
For example, you might have a JSON file with contents like
{
"filename": "c:\file1.xls",
"some_param": 6,
"some_other_param": True
}
and your script would look like
import json
import sys
with open(sys.argv[1]) as f:
config = json.load(f)
xml.open(config['filename'])
while True:
do stuff using config['some_param'] and config['some_other_param']

Reference a Python file in another Python file

I have two Python files, global.py and test_train.py, both sitting in the same folder. I am trying to allow test_train.py to access everything (functions, variables, etc. in global.py). I cannot get it to work. In the same folder is init.py. I have tried import global and have also referenced Source a Python's file from another Python file, but nothing seems to work. Suggestions?
You should change your file (global.py) name, when you import global.py,
the module name global will conflict with python keyword global
import global # global is keyword in python, you should avoid using this name
# so it will occur error
import global_test # this line is OK, if your .py name is global_test
Typically import global should work.
However, if it doesn't work, you should do a check to see if the import is happening successfully.
A print statement at the end of the global.py script should suffice to tell you so.
Otherwise, if the import is working, then you should try changing your code by encapsulating the entire contents of the global.py in a class, and then creating an object of that class in your test_train.py script to call its functions and attributes.
You can also make use of getattr function to call directly from global.py

python get the script which imported my script

I want to make my own programming language based on python which will provide additional features that python wasn't provide, for example to make multiline anonymous function with custom syntax. I want my programming language is so simple to be used, just import my script, then I read the script file which is imported my script, then process it's code and stop anymore execution of the script which called my script to prevent error on syntax...
Let say there are 2 py file, main.py and MyLanguage.py
The main.py imported MyLanguage.py
Then how to get the main.py file from MyLanguage.py if main.py can be another name(Dynamic Name)?
Additional information:
I using python 3.4.4 on Windows 7
Like Colonder, I believe the project you have in mind is far more difficult than you imagine.
But, to get you started, here is how to get the main.py file from inside MyLanguage.py. If your importing module looks like this
# main.py
import MyLanguage
if __name__ == "__main__":
print("Hello world from main.py")
and the module it is importing looks like this, in Python 3:
#MyLanguage.py
import inspect
def caller_discoverer():
print('Importing file is', inspect.stack()[-1].filename)
caller_discoverer()
or (edit) like this, in Python 2:
#MyLanguage.py
import inspect
def caller_discoverer():
print 'Importing file is', inspect.stack()[-1][1]
caller_discoverer()
then the output you will get when you run main.py is
Importing file is E:/..blahblahblah../StackOverflow-3.6/48034902/main.py
Hello world from main.py
I believe this answers the question you asked, though I don't think it goes very far towards achieving what you want. The reason for my scepticism is simple: the import statement expects a file containing valid Python, and if you want to import a file with your own non-Python syntax, then you are going to have to do some very clever stuff with import hooks. Without that, your program will simply fail at the import statement with a syntax error.
Best of luck.

Using command line args from different files in python

I recently discovered (Much to my surprised) you can call command line args in files other than the one that is explicitly called when you enter it.
So, you can run python file1.py abc in command line, and use sys.argv[1] to get the string 'abc' from within file2.py or file3.py.
I still feel like this shouldn't work, but I'm glad it does, since it saved me a lot of trouble.
But now I'd really appreciate an answer as to why/how this works. I had assumed that sys.argv[1] would be local to each file.
As for the how/why, sys is only imported once (when python starts up). When sys is imported, it's argv member gets populated with the commandline arguements. Subsequent import statements return the same sys module object so no matter where you import sys from, you'll always get the same object and therefore sys.argv will always be the same list no matter where you reference it in your application.
Whether you should be doing commandline parsing in more than one place is a different question. Generally, my answer would be "NO" unless you are only hacking together a script to work for the next 2 or 3 days. Anything that you expect to last should do all it's parsing up front (probably with a robust argument parser like argparse) and pass the data necessary for the various functions/classes to them from it's entry point.

Finding function declarations in Ubuntu on Python

I have a vaguely defined function of a class Graph of a module I call gt (it is graph-tool). so i declare g = gt.graph() then want to use g.degree_property_map but do not know how. Therefore I want to see where in code g.degree_property_map or in this case just the function, is defined. How can I find that? I'm working on command line on a vm.
Thanks
For reference the library in question is graph-tool - http://projects.skewed.de/graph-tool/
Also I am currently importing it using from graph_tool.all import * . that is of course somewhat of a problem.
You could use inspect.getsource(gt.Graph.degree_property_map). (You have to import inspect.)
Of course, what you pass into getsource() will change depending on how you imported Graph. So if you used from graphtools.all import *, you'd just need to use inspect.getsource(Graph.degree_property_map).
If you open interactive python (type python and hit ENTER on the command line), you should be able to run the command help(<graph's module name>), then, under the FILE section of the help documentation that is generated, you should see the absolute path to the code you are interested in.
For example, I just ran:
import numpy
help(numpy)
# Returned documentation containing:
# FILE
# /usr/lib/python2.7/dist-packages/numpy/__init__.py
Also,
import my_module # A module I just created that contains the "Line" class
help(my_module)
# Returned documentation containing:
# FILE
# /home/<my user name>/Programming/Python/my_module.py
If it is a normal function (not a builtin, ufunc, etc) you can try using the func_code attribute
For example:
>>> inspect.iscode
<function iscode at 0x02EAEF30>
>>> inspect.iscode.func_code
<code object iscode at 02EB2B60, file "C:\Python27\lib\inspect.py", line 209>
Never mind I just did help(graph_tool) and manually jumped through code. Thanks for the help though!

Categories

Resources