Syntax error using sys.argv as argument in function - python

Got syntax error caused by this line of code
def load(sys.argv):
with open(sys.argv[1]) as file:
reader = json.load(file)
return reader['json']
Message from stderr:
def load(sys.argv):
^
SyntaxError: invalid syntax
Of course, I have imported sys.
Actually, parameters inside the function, that use sys.argv, work properly. Does anyone know a solution to this?

Functions pass in parameters and variable names, you don't declare them in there. You code should look like the following
def load(arguments):
# Your Code
firstArg = arguments[0]
load(sys.argv)

You can't use sys.argv as a function argument.
Just rename the argument and it will work:
import sys
def load(args):
# your logic
print(load(sys.argv))

If you are going to specify you want sys.argv[1] inside the function, you wouldn't need any sort of parameter. You could make it a function that needs no arguments.
import sys
def load():
with open(sys.argv[1]) as file:
# code to execute...
# code to execute...
load()
My suggestion is only applicable if you only want to open one file using one command line parameter (at index 1). If you wanted to open others using other command line parameters, you would need a parameter in your function like 'args' (like David Teather said) to make the code more flexible.
Parameters are set as new variable names to be used within the scope of your function. In your code, it's like you are trying to set 'sys.argv' as a function name, which doesn't work because it is already a function.

Related

How to call variables from two different python modules(bi-directional)

I am stuck in resolving a problem using python. Problem is I have to pass a variable value of module(python_code1.py) to a different module(python_code2.py). Based on the variable value, need to do some calculation in the module python_code2.py and then need to capture output value in the same module(python_code1.py) for further calculations.
Below is the snapshot of my code logic :
python_code2.py
import python_code1
data = python_code1.json_data
'''
Lines of code
'''
output = "some variable attribues"
python_code1.py
import python_code2
json_data = {"val1": "abc3","val1": "abc3","val1": "abc3"}
input_data = python_code2.output
''''
Lines of code using input_data variable
'''''
when I execute python python_code1.py, this is giving error:
AttributeError: module 'python_code2' has no attribute 'output'
I feel like I am not doing it in write way, but considering my code complexity and lines of code, I have to use these 2 module method.
Putting your code at the top-level is fine for quick throw away scripts, but that's about all. The proper way to organize your code for anything non-trivial is to define functions, so you can pass values as arguments and get results as return value.
If there's only on script using those functions, you can keep them in the script itself.
If you have multiple scripts needing to use the same functions, move those functions to a module and import this module from your scripts.

TypeError: function missing 1 required positional argument: 'path' Flask Python

I have a static folder and my main usage is a sub-directory there that is found in
root/static/images/monkeys
I have a flask app and I have a variable like so:
app = Flask(__name__)
monkeys_folder_path = os.path.join(app.static_folder, 'images', 'monkeys')
I use it in two functions, one function serves a static image in that folder, this function works:
#app.route('/monkey/<address>')
def serve_static(address):
# this creates an image in /static/images/monkeys
monkey_generator.create_monkey_from_address(address)
filename = address + ".png"
return send_from_directory(monkeys_folder_path,filename)
I also have another function that uses this path, this function deletes images after X seconds from the folder
def remove_monkey_images(path):
threading.Timer(5.0, remove_monkey_images).start()
# this function iterates in a loop over the files in the path and deletes them
helper_functions.delete_images(path)
This function does not work, when I run the server locally I get
File "C:\Users\user\AppData\Local\Programs\Python\Python36-32\lib\threading.py", line 1182, in run
self.function(*self.args, **self.kwargs)
TypeError: remove_monkey_images() missing 1 required positional argument: 'path'
I call the function like so:
remove_monkey_images(path=monkeys_folder_path)
Thanks.
When you create the Timer, you have to pass it the called function's arguments, like this:
threading.Timer(5.0, remove_monkey_images, (path,)).start()
Source
As for the rest of your code I don't really know if it's consistent, but at least that's the cause of the error you're getting.
Python function can have positional or keyword parameters. Your function definition
def remove_monkey_images(path)
describe function with one positional parameter. This function could be called only with one positional argument like
remove_monkey_images(monkeys_folder_path)
If you want to use keyword argument you needs
def remove_monkey_images(path='/some_default_path')
In this case you could call function both with
remove_monkey_images(monkeys_folder_path)
and
remove_monkey_images(path=monkeys_folder_path)
and
remove_monkey_images()
In latter case inside function argument path will have default value '/some_default_path'.
there is a syntax issue with your problem.
Either do this:
remove_monkey_images(monkeys_folder_path)
instead of
remove_monkey_images(path=monkeys_folder_path)
or
Update your function definition as:
def remove_monkey_images(path=None):
threading.Timer(5.0, remove_monkey_images).start()
# this function iterates in a loop over the files in the path and deletes them
helper_functions.delete_images(path)

Run tests from code with arg

I used to run tests with a command like
pytest.main('-s path_to_file --my_fixtures_arg1 arg_value')
At the moment, such a call is considered obsolete, and you need to call this command through a list of arguments. But I can not pass the necessary parameters in any way. Who knows the solution?
I'm currently using list of arguments since passing string was deprecated. In your case I think this one should work:
arguments = ['-s', '--my_fixtures_arg1=arg_value', 'path_to_file']
pytest.main(args=arguments)
Currently pytest uses shlex.split to split a string into a list of arguments.
You can do the same if your string comes from DB, config file or such:
import shlex, sys
args_list = shlex.split(args_string, posix=sys.platform != "win32")

How to use Parameters in Python Luigi

How do I pass in parameters to Luigi? if I have a python file called FileFinder.py with a class named getFIles:
class getFiles(luigi.Task):
and I want to pass in a directory to this class such as:
C://Documents//fileName
and then use this parameter in my run method
def run(self):
how do I run this in command line and add the parameter for use in my code? I am accustomed to running this file in command line like this:
python FileFinder.py getFiles --local-scheduler
What do I add to my code to use a parameter, and how do I add that parameter to the command line argument?
Also, as an extension of this question, how would I use multiple arguments? or arguments of different data types such as strings or lists?
As you have already figured out, you can pass arguments to luigi via
--param-name param-value
in the command line. Inside your code, you have to declare these variables by instantiating the Parameter class or one of it's subclasses. The subclasses are used to tell luigi if the variable has a data-type that is not string. Here is an example which uses two command line arguments, one Int and one List:
import luigi
class testClass(luigi.Task):
int_var = luigi.IntParameter()
list_var = luigi.ListParameter()
def run(self):
print('Integer Param + 1 = %i' % (self.int_var + 1))
list_var = list(self.list_var)
list_var.append('new_elem')
print('List Param with added element: ' + str(list_var))
Note that ListParams actually get converted to tuples by luigi, so if you want to do list operations on them, you have to convert them back first (This is a known issue, but doesn't look like it will be fixed soon).
You can invoke the above module from the command line like this (i have saved the code as a file called "testmodule.py" and made the call from inside the same directory):
luigi --module testmodule testClass --int-var 3 --list-var '[1,2,3]' --local-scheduler
Note here that for variables containing a _, this has to be replaced by -.
The call yields (along with many status messages):
Integer Param + 1 = 4
List Param with added element: [1, 2, 3, 'new_elem']
So I think this works, in the code I added:
fileName = luigi.Parameter()
if i run this in the command line:
python FileFinder.py getFiles --local-scheduler --getFiles-fileName C://Documents//fileName
but if anyone has any advice on parameters of different types and how to use them, especially numbers and lists, please let me know.
Adding to Toterich's answer.
While passing a list of string arguments as a ListParameter():
python file_name.py --local-scheduler TaskName --arg '["a","b"]'
The string arguments must be enclosed in double-quotes and not single quotes otherwise it'll give a JSONParsing error.

argparse: how to parse a single string argument OR a file listing many arguments?

I have a use case where I'd like the user to be able to provide, as an argument to argparse, EITHER a single string OR a filename where each line has a string.
Assume the user launches ./myscript.py -i foobar
The logical flow I'm looking for is something like this:
The script determines whether the string foobar is a readable file.
IF it is indeed a readable file, we call some function from the script, passing each line in foobar as an argument to that function. If foobar is not a readable file, we call the same function but just use the string foobar as the argument and return.
I have no ability to guarantee that a filename argument will have a specific extension (or even an extension at all).
Is there a more pythonic way to do this OTHER than just coding up the logic exactly as I've described above? I looked through the argparse tutorial and didn't see anything, but it also seems reasonable to think that there would be some specific hooks for filenames as arguments, so I figured I'd ask.
A way would be:
Let's say that you have created a parser like this:
parser.add_argument('-i',
help='...',
type=function)
Where type points to the function which will be an outer function that evaluates the input of the user and decides if it is a string or a filename
More information about type you can find in the documentation.
Here is a minimal example that demonstrates this use of type:
parser.add_argument('-d','--directory',
type=Val_dir,
help='...')
# ....
def Val_dir(dir):
if not os.path.isdir(dir):
raise argparse.ArgumentTypeError('The directory you specified does not seem to exist!')
else:
return dir
The above example shows that with type we can control the input at parsing time. Of course in your case the function would implement another logic - evaluate if the input is a string or a filename.
This doesn't look like an argparse problem, since all you want from it is a string. That string can be a filename or a function argument. To a parser these will look the same. Also argparse isn't normally used to run functions. It is used to parse the commandline. Your code determines what to do with that information.
So here's a script (untested) that I think does your task:
import argparse
def somefunction(*args):
print(args)
if __name__=='__main__':
parser=argparse.ArgumentParser()
parser.add_argument('-i','--input')
args = parser.parse_args()
try:
with open(args.input) as f:
lines = f.read()
somefunction(*lines)
# or
# for line in lines:
# somefuncion(line.strip())
except:
somefunction(arg.input)
argparse just provides the args.input string. It's the try/except block that determines how it is used.
================
Here's a prefix char approach:
parser=argparse.ArgumentParser(fromfile_prefix_chars='#',
description="use <prog -i #filename> to load values from file")
parser.add_argument('-i','--inputs')
args=parser.parse_args()
for arg in args.inputs:
somefunction(arg)
this is supposed to work with a file like:
one
two
three
https://docs.python.org/3/library/argparse.html#fromfile-prefix-chars

Categories