Concatenating strings in Python - python

How can I properly concatenate a variable inside an string in Python?
I am trying to pass service in "Database Connections\\'service'.sde" and (r"C:\GIS\Maps\'.+service+.'.mxd")
service ="Electric"
sde = "Database Connections\\'service'.sde"
mxd = arcpy.mapping.MapDocument(r"C:\GIS\Maps\'.+service+.'.mxd")
so the output looks like
sde = "Database Connections\\Electric.sde"
mxd = arcpy.mapping.MapDocument(r"C:\GIS\Maps\Electric.mxd")

I think a better way to do this is using os.path.join:
import os
mxd = arcpy.mapping.MapDocument(os.path.join(*"C:\\GIS\\Maps\\".split('\\')
+ ["{}.mxd".format(service)]))
Also, note that your back-slashes need to be escaped.

This is how Python's string concatenation works:
sde = "Database Connections\\" + service + ".sde"
mxd = arcpy.mapping.MapDocument("C:\\GIS\\Maps\\" + service + ".mxd")

An alternative which bypasses the issue of raw strings can't end with a single backslash:
r'C:\GIS\Maps\%s.mxd' % service
and
r'C:\GIS\Maps\{}.mxd'.format(service)
both work fine, dodging the issue with the string ending in a backslash.

Related

How to add .htm to email body using win32com

I need to use win32com.client to make an email where I add a signature with the .htm extension to the mail.HtmlBody. However, each time I do this, I get UnicodeDecodeError.
In other words, how do I correct the UnicodeDecodeError problem and add my string & htm file to the HtmlBody?
self.mail = win32.Dispatch('outlook.application').CreateItem(0)
self.curText = str(self.email.currentText())
self.projectNameT = ' '.join(self.curText.split(' ')[7:])
self.mail.To = 'ABC#XYZ.com'
self.mail.Subject = "Subject: " + str(self.projectNameT)
self.someStr = 'Hello '
self.html_url = open("SomePath//Signature.htm",encoding = 'utf16')
self.data = self.html_url.read()
self.mail.HtmlBody = self.someStr + ('<p>self.data</p>')
If you want to insert a signature in using python and fully programatically, Redemption exposes the RDOSignature object which implements ApplyTo method (it deals with signature image files and merges HTML styles). Because with the outlook security patch, a lot is unable to be done inherrently, so you must work around this before you can procede as normal

Trying to format a connection string in Python - unable to replace with variable

I am trying to create a connection string in Python - the goal is to have a list of tables/servers to access and it'll iterate through based on a list earlier.
I've got the query written (using """select * from """ worked) , but I cannot seem to get the connection string to behave. Yes. the "{SQL Server}" needs to be in curly-brackets.
server_name = "myservername"
#this doesn't work:
con_string = ('Driver={{SQL Server}};Server={server_name};Database={mydatabase};App=myappname;Trusted_Connection=yes')
Nor does this
con_string = ('Driver={{SQL Server}};'
'Server={};'.format(server_name)
'Database=mydatabase;'
'App=myappname;' # It's not "application name"!
'Trusted_Connection=yes')
Nor this:
serverstring = 'Server={};'.format(server_name)
con_string = ('Driver={{SQL Server}};'
'{serverstring}'
'Database=mydatabase;'
'App=myappname;' # It's not "application name"!
'Trusted_Connection=yes')
Any help greatly appreciated.
To create a format string you need f at the beginning. So, for example, your third example should be:
serverstring = 'Server={};'.format(server_name)
con_string = ('Driver={{SQL Server}};'
f'{serverstring}'
'Database=mydatabase;'
'App=myappname;' # It's not "application name"!
'Trusted_Connection=yes')
Give this a go. The curly brackets are doubled up (as you have above) to escape themselves. Is this what you're looking for?
Python 3.6 introduces new string formatting functionality (f-strings) which uses variable replacement. But for those of us still on 3.5, this works nicely.
con_string = ('Driver={{SQL Server}};'
'Server={svr};'
'Database={db};'
'App={app};'
'Trusted_Connection={tc}').format(svr='SERVER01',
db='MyDB',
app='MyApp',
tc='Yes')
Here is the output:
Driver={SQL Server};Server=SERVER01;Database=MyDB;App=MyApp;Trusted_Connection=Yes

Can one use, or how to avoid using, a colon (":") as the start of a path to an sqlite database

I am creating a plugin for QGIS (QGIS Plugin Builder). The relative paths to the plugin directory need to start with a colon. The icon for example is loaded like this:
icon_path = ':/plugins/into_sqlite/icon.png'
When I try to do the same for the sqlite database the database fails to load:
connection = sqlite3.connect(":/plugins/PLUGINNAME/database.sqlite")
OperationalError: unable to open database file
But when I try the same giving the absolute path it works:
connection = sqlite3.connect("/home/USERNAME/.qgis/python/plugins/PLUGINNAME/database.sqlite")
OperationalError: unable to open database file
I think that the problem is that the path starts with a colon and sqlite uses the colon as a special character to for example load a database in memore:
connection = sqlite3.connect(":memory:")
But I need to use realtive paths. How can I supply the path and escape the colon or start the path without the colon?
I now went around the problem by using this code:
path = abspath(":/plugins/PLUGINNAME/")
path_abs = path.replace(":", ".qgis2/python")
path_db = join(path_abs, "db.sqlite")
connection = sqlite3.connect(path_db)
The variables have these values:
path = "/home/USERNAME/:/plugins/PLUGINNAME"
path_abs = "/home/USERNAME/.qgis2/python/plugins/PLUGINNAME"
path_db = "/home/USERNAME/.qgis2/python/plugins/PLUGINNAME/db.sqlite"
Another suggestion:
On IRC the suggestion was:
curr_path = os.path.dirname(os.path.abspath(__file__))
self.path_db = os.path.join(curr_path, 'db.sqlite')

python generate_signed_query_string blob return wrong query string

I am trying to share a blob in a private Azure blob storage container using Python SDK, below is the code:
try:
accss_plcy = AccessPolicy()
accss_plcy.start = '2013-03-12'
accss_plcy.expiry = '2013-03-13'
accss_plcy.permission = 'r'
signed_identifier = 'YWJjZGVmZw=='
sap = SharedAccessPolicy(accss_plcy, signed_identifier)
qry_str = sas.generate_signed_query_string('picture/xxx.jpg','blob', sap)
except Exception as ex:
abort(400, 'Download blob fail %s'%ex)
return sas._convert_query_string(qry_str)
Below is the query string return :
st=2013-03-12&se=2013-03-13&sp=r&resource=blob&sig=FI88prUINf58Seg5Nwo6Uj5RP9FxXGZBBSKi7pybmeQ=&
You may notice that resource=blob, but it should return sr=b.
How should I solve the problem?
It looks like a bug in the SDK. Since the code for Azure SDK is open source, you could possibly download the code and make change to this file: https://github.com/WindowsAzure/azure-sdk-for-python/blob/master/src/azure/storage/sharedaccesssignature.py. Looking at the source code in that file, you would need to change the following line of code (line 129):
convert_str += SIGNED_RESOURCE_TYPE + '=' + query_string[SIGNED_RESOURCE] + '&'
to
convert_str += SIGNED_RESOURCE + '=' + query_string[SIGNED_RESOURCE] + '&'
Also I noticed that you're passing blob as the resource type in your code above:
qry_str = sas.generate_signed_query_string('picture/xxx.jpg','blob', sap)
You would need to pass 'b' instead of 'blob'
qry_str = sas.generate_signed_query_string('picture/xxx.jpg','b', sap)
I think that should do the trick. Also please ensure that you submit a bug on Github so that the team responsible for maintaining the code can fix it.

File not being released

Ok so I have to run some queries in access 07 then compact and repair it. I am using python and win32com to do this. The code I'm currently using is this.
import os;
import win32com.client;
DB1 = 'db1.mdb'
DB2 = 'db1N.mdb'
DB3 = 'db2.mdb'
DBR = r'db1.mdb'
access = win32com.client.Dispatch("Access.Application")
access.OpenCurrentDatabase(DBR)
DB = access.CurrentDb()
access.DoCmd.OpenQuery("1")
access.DoCmd.OpenQuery("2")
access.DoCmd.OpenQuery("3")
access.CloseCurrentDatabase()
access.Application.Quit();
os.system('copy "db1.mdb" "db2.mdb"')
access = win32com.client.Dispatch("Access.Application")
access.CompactRepair(DB3,DB2)
access.Application.Quit();
os.remove("db2.mdb")
os.remove("db1.mdb")
os.rename("db1N.mdb","db1.mdb")
The problem is that I get this error.
WindowsError: [Error 32] The process cannot access the file because it is being used by another process: 'db1.mdb'
I dont know why I am getting this error seeing as I am quiting access which should close the file. Any Idea how to fix this would be greatly appreciated.
Your code includes this line:
DB = access.CurrentDb()
When that line executes, CurrentDb() references db1.mdb. Then you later get WindowsError at:
os.remove("db1.mdb")
So I'm wondering if the variable DB still holds a reference to db1.mdb. Perhaps you could first try del DB before os.remove().
Or, since your code isn't actually using that DB variable, just get rid of it.
I made some changes to get your example to work for me. To solve your problem add DB.Close();
import os;
import win32com.client;
path='C:/project/714239'
os.chdir(path)
DB1 = 'db1.mdb'
DB2 = 'db1N.mdb'
DB3 = 'db2.mdb'
access = win32com.client.Dispatch("Access.Application")
access.OpenCurrentDatabase(path + '/' + DB1, False)
DB = access.CurrentDb()
DB.Close(); #ADDED THIS
access.CloseCurrentDatabase()
access.Application.Quit();
os.system('copy ' + DB1 + ' ' + DB2)
access = win32com.client.Dispatch("Access.Application")
access.CompactRepair(path + '/' + DB2, path + '/' + DB3, True)
access.Application.Quit();
os.remove(DB2)
os.remove(DB1)
os.rename(DB3,DB1)

Categories