I want to do a subprocess.call to create a file (and eventually populate it). Here's my code:
#!/usr/bin/python
import sys
import subprocess
import psycopg2
import base64
import urlparse
sys.path.append('/var/www/cgi-bin')
def index(req):
out = ""
mkFile = str("touch /etc/httpd/conf/ipForward/90.conf")
subprocess.call([mkFile],shell=True)
return out
mkFile = str("touch /etc/httpd/conf/ipForward/111.conf")
subprocess.call([mkFile],shell=True)
Right now only the bottom command works, but these two subprocesses should do the same exact thing (I've named the file differently for testing purposes). I know there is a better way to do this but, for my own edification (and sanity) can someone explain the difference?
~~~~~~~~~~~~~~~~~~~~~~~EDIT COMPLETE CODE~~~~~~~~~~~~~~~~~~~~~
def index(req):
out = ""
conn = psycopg2.connect("dbname='pwp' host='localhost' user='~~~' password='~~~~~'")
c = conn.cursor()
inClCN = str(req.subprocess_env['SSL_CLIENT_S_DN_CN'])
c.execute("select * from Users where cn = '{0}';".format(inClCN))
rows = c.fetchall()
for row in rows:
port = row[0]
mkFile = str("touch /etc/httpd/conf/ipForward/{0}.conf".format(port))
subprocess.call([mkFile],shell=True)
insert = r"""Listen {0}\n\n<VirtualHost _default_:{1}>\n\nDocumentRoot '/var/www/html/'\nDirectoryIndex indexAlex.py\n\nRewriteEngine On\n\nErrorLog /etc/httpd/logs/error_log\nTransferLog /etc/httpd/logs/access_log\nLogLevel warn\n\n\nNSSVerifyClient require\n\nNSSEngine on\nNSSFIPS on\nNSSProtocol(MORE CONF STRING)</VirtualHost>""".format(port,port)
confFile = str('echo "{0}" >> /etc/httpd/conf/ipForward/{1}.conf'.format(insert,port))
subprocess.call([confFile],shell=True)
return out
The only reason I need the req is to get the environmental variable from apache. I don't really know how that works but I've been using that in other code without subprocesses.
Your first call to subprocess.call is within a def statement. A def statement doesn't actually call anything under it right away, instead it defines a function, which is a block of code you can reuse anywhere else.
The first "call" to subprocess.call doesn't do anything because you are just defining it as part of a reusable piece of code, but never actually using this reusable piece of code.
If you want to "use" the first call, you need to call the function you just defined using def:
Add the following to the end of your script:
index(None)
and the "first" call should happen, but after the first.
You can read more about how the def statement works and about functions here.
Related
I am new to Stackoverflow so I will try to ask the question as detailed as possible. I am facing an issue where I call a function to write a value to a python file, and another function to return this written value. However, the function that supposed to return this written value does not return the most updated value after the write function.
I have done multiple researches and tried multiple methods from other questions posted in Stackoverflow but it still didn't work for me.
Here is what I currently have:
In test.py
import random
import string
from test_value import *
def write():
letters = string.ascii_letters
value_to_be_passed = ''.join(random.choice(letters) for i in range(10))
f = open("test_value.py", "w")
f.write('value="' + value_to_be_passed + '"')
f.close()
def read():
print(value)
write()
read()
In test_value.py
value="MutmHDlVQj"
If you run this file, it will generate a new string and store this new string into test_value.py. But when the function read() runs, it does not print out the newly generated string. It seem as though when I run this program, python will immediately store the value in test_value.py in it's memory and does not return the new value when called.
I have tried fsync, flush, with open but it still doesn't work. It won't be ideal to read the file as a plaintext as I might be storing multiple variables in test_value.py so that my program can call the value of the respective variables.
You can run the code in your ide, upon the first run it will print MutmHDlVQj in your terminal even though the goal is supposed to print the newly generated string.
Does anyone know how this could be solved? Thank you in advance.
Workaround Solution
Thanks to tripleee that gave me the idea of this cheap solution. However, I am sure there are better methods that can be done to solve this issue. May the experts give your opinions on this!
Instead of importing at compile time, I ran the importing when I really needed it.
def read():
from test_value import *
print(value)
The import happens when your script is compiled, before it runs and writes anything to the new file. If you want to import something during runtime, you can do that with importlib; but this seems fundamentally like an XY problem. If your task is to serialize some data, use pickle or simply save the data in a standard format like JSON.
from import method you can't pass a variable so simply for a return value, you must specify in test_value.py a return function.
here's the functioning code:
import random
import string
from test_value import value
def write():
letters = string.ascii_letters
value_to_be_passed = ''.join(random.choice(letters) for I in range(10))
f = open("test_value.py", "w")
f.write('value="' + value_to_be_passed + '"')
f.close()
def read():
returned_value = value()
print(returned_value)
write()
read()
in test_value.py:
def value():
value="SbjvLSYfNs"
return value
written like this I have a functioning code that prints the value returned from another python file like you asked.
hope it helps in the future, but remember that if you want to return a value, you must specify the return function
I have two tests in which I'm trying to import things from the same myconfig.py file. But I need some variables in myconfig.py to be changed after every test so the next can use a new one.
Is there any possible way to do it?
I already have function that re-writes info and it works correctly, but both tests import the very first version of myconfig.py.
I tried to use fixtures, but it didn't work. I also tried to run/exec myconfig.py before every launch, didn't help either.
I use two same small tests, run them as a package called test_package.
from myconfig import url, file_name, line_index
from test_package.functions_filee import upgrade_number
from test_package.pages.my_page import MyPageObject
from file_where_info_should be_rewritten import phone_number
def test_rewrite_number(self, browser):
my_page = MyPageObject(browser, url)
my_page.go_to_site()
my_page.input_phone_number(phone_number)
upgrade_number(file_name, line_index, phone_number)
upgrade_number function code:
def upgrade_number(file_name, line_index, phone_number):
with open(file_name, 'r+') as f:
lines = f.readlines()
new_number = str(int(phone_number) + 1)
new_str = f"phone_number = '{new_number}'\n"
lines[line_index] = new_str
f.seek(0)
f.writelines(lines)
File, where info should be rewritten consists of only a single line:
phone_number = "1111111111"
So basically I want the first test to import 1111111111 as a phone number, then increase it to 1111111112 so that the second test can use 1111111112 as its test data.
EDIT: I did it like this
import sys
import importlib
importlib.reload(sys.modules['dynamic_vars'])
from dynamic_vars import *
Eventually I gave up on this method of making new phone number for every test, but maybe it will be helpful for anyone
The classical pattern for this is called Test setup. In pytest you have setup_method which you can implement to reload your config and it will be done before each test is executed.
Similarly, you can use teardown_method to run code after each test. Your test can also set a class variable so each invocation of setup_method or teardown_method knows which value to use.
BUT
You should not do what you explain here. This makes tests dependent on each other which is a very problematic antipattern. Instead, make each test setup what it needs explicitly at the beginning. So, if a second test needs 1111111112 as its input data, specify this at the beginning of the test - by calling an utility function that will prepare the config appropriately.
This not only makes the tests independent - it also makes them more readable, as it's clear at the beginning of the test what the scenario is.
When I run the below code my websites or steam still open. Shouldn't I need to state print(link) or print(steam) for them to open?
import os
import webbrowser
import subprocess
import random
urls = ['https://www.ft.com/',
'https://www.youtube.com/watch?v=xvqcFcfhUVQ',
'https://roadmap.sh/backend',
'https://www.youtube.com/watch?v=YYXdXT2l-Gg&list=PL-osiE80TeTskrapNbzXhwoFUiLCjGgY7']
foxpath = 'C:/Program Files/Mozilla Firefox/Firefox.exe %s'
link = webbrowser.get(foxpath).open(random.choice(urls))
steam = subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
Why does this happen?
I eventually want to run the program from a function call, like below.
def wildcard():
print(random.choice(link, steam))
wildcard()
No, there is nothing special about print. print is just a function that takes in some value and displays it to the user.
If you had instead steam = 3 * 4, would you be surprised to learn that the value 12 is computed, and steam becomes a name for that value, even if you don't do anything with it? It's the same thing here - calling subprocess.call causes the program to launch, and it has nothing to do with the name steam, nor anything that you do or don't do with that name subsequently.
If you were to add the print(steam) line that you have in mind, what it would display (after you close steam and control returns to your program) is the "return code" of that program - this gets into the details of how your operating system works, but most likely it would be something like 0.
If you want something that you can later call in order to launch Steam - well, that's a function. Like you already know how to do:
def steam():
subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
As soon as you issue webbrowser.get or subprocess.call, they execute. Your variables are really storing the return values of those functions, not aliases to those function calls.
If you want to alias the function calls as it appears you are intending, you could do something like this:
def open_link():
return webbrowser.get(foxpath).open(random.choice(urls))
def open_steam():
return subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
Then your top level would be:
def wildcard():
random.choice([link, steam])()
wildcard()
Note the syntax difference for choosing the functions randomly. See this answer for more clarification.
You do invoke something:
steam = subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
The documentation for subprocess.call is clear on what the call method does: it invokes the given argument as a subprocess.
The problem is that your code isn't inside a function, so, when you execute it, it runs all the diretives including
steam = subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
Which calls C:/Program Files (x86)/Steam/Steam.exe, opening your steam app.
Hope it helps.
Thank you, I understand now. I actually just resolved the problem with the following
def wildcard():
for x in range(1):
rand = random.randint(1, 10)
if rand > 5:
link = webbrowser.get(foxpath).open(random.choice(urls))
else:
subprocess.call(['C:/Program Files (x86)/Steam/Steam.exe'])
wildcard()
Is it possible to intercept interpreter's code before it executes?
Let's say I want to handle a case like:
>>> for f in glob.glob('*.*'): # I'd like to intercept this code before it executes
... something_to_do(f) # and play with it in some dangerous fashion :)
...
ERROR: Using glob not allowed. # e.g.
But there are tons of other examples (like altering the code, or sending it somewhere).
I can write my own interpreter, but that's not really the point.
Ok, solved it by creating new module which starts new interpreter instance and do whatever.
I just put the code below in the module and import it.
import code
class GlobeFilterConsole(code.InteractiveConsole):
def push(self, line):
self.buffer.append(line)
source = "\n".join(self.buffer)
if 'glob' in source: # do whatever you want with the source
print('glob usage not allowed')
more = False
else:
more = self.runsource(source, self.filename)
if not more:
self.resetbuffer()
return more
console = GlobeFilterConsole()
console.interact()
This is a minimum code:
import sqlite3 as sq3
import os
import sys
def main(argv):
q = 'select * from table_name;'
db = 'test.db'
con = sq3.connect(db)
cur = con.cursor()
cur.executescript(q) // cur.execute(q) will work
print cur.fetchone()
if __name__ == '__main__':
sys.exit(main(sys.argv))
My problem is executescript always fails while execute works fine. Is it because executescript is Nonstandard or some libraries I missed?
executescript isn't supposed to return anything, what would it return? The last statement? The first statement? or maybe that one in the middle.
Since it allows you to execute multiple SQL statements there is no way to tell which one you want to have returned.
executescript() is for executing multiple SQL commands, i.e., a script. What is the return value of multiple SQL commands? Hard to say, which is why executescript() returns None. You're not doing anything wrong nor do you have anything missing in your installation.