Home Php C# Sql C C++ Javascript Python Java Go Android Git Linux Asp.net Django .net Node.js Ios Xcode Cocoa Iphone Mysql Tomcat Mongodb Bash Objective-c Scala Visual-studio Apache Elasticsearch Jar Eclipse Jquery Ruby-on-rails Ruby Rubygems Android-studio Spring Lua Sqlite Emacs Ubuntu Perl Docker Swift Amazon-web-services Svn Html Ajax Xml Java-ee Maven Intellij-idea Rvm Macos Unix Css Ipad Postgresql Css3 Json Windows-server Vue.js Typescript Oracle Hibernate Internet-explorer Github Tensorflow Laravel Symfony Redis Html5 Google-app-engine Nginx Firefox Sqlalchemy Lucene Erlang Flask Vim Solr Webview Facebook Zend-framework Virtualenv Nosql Ide Twitter Safari Flutter Bundle Phonegap Centos Sphinx Actionscript Tornado Register | Login | Edit Tags | New Questions | 繁体 | 简体


10 questions online user: 12

12
votes
answers
16 views
+10

根据最大值的长度从python中找到项目列出的dictonary?

假设我有一个字典,如:

  dicl = {'amazon':[668,667,879],'flipkart':[678],'嘿':[89 ,79]}   

我想根据项目长度的降序打印字典项目。

我想要的输出:

  {'amazon':3,'hey':2,'flipkart':1}   < p>但是我按照项目的降序显示结果,而我想根据项目的降序显示项目? 

我尝试过:

  cov_m = {k:len(v)表示k,v表示已排序(dicl.items())}   

当前输出:

  {'amazon' :3,'flipkart'
    
        
沙发
+40
+50

您可以将 lambda 函数作为参数传递给 sorted 函数,以指定您的排序条件:

  dicl = { 'amazon':[668,667,879],'flipkart':[678],'hey':[89,79]} cov_m = {k:len(v)for k,v in sorted(dicl.items( ),key = lambda i:-len(i [1]))} print(cov_m)  

输出:

  {'amazon':3 ,'嘿':2,'flipkart':1}   

这里, len(i [1])是值的长度,我'我按 -len(i [1])(负长度)排序,因为你希望它们按降序排列,如果有更高级的排序标准,你应该使用,reverse = True)而不是。

谢谢Geek先生。假设我需要像这样保留项目细节:{'amazon':( [668,667,879],3),'hey':( [89,79],2),'flipkart':( [678] ,1)}。怎么做我尝试过这样的事情,但没有得到理想的结果。我尝试过{k [0]:(len(v))表示k,v表示已排序(dicl.items(),key = lambda x:len(x [1]),reverse = True)} - Mishra S 8月29日13:14

@MishraS只需在cov_m的定义中将k:len(v)改为k:(v,len(v))。 - MrGeek 8月29日13:17

+20

sorted 与自定义键一起使用。

例如:

  dicl = {'amazon':[ 668,667,879],'flipkart':[678],'嘿':[89,79]} print({k:len(v)表示k,v表示已排序(dicl.items(),key = lambda) x:len(x [1]),reverse = True)})  

输出:

  {'amazon' :3,'嘿':2,'flipkart':1}  
     
			
        
+20

我会将数据转换为排序列表:

  data = {'amazon':[668,667,879],'flipkart':[678],'嘿': [89,79]} sorted_data = sorted([{'name':k,'val':len(v)}代表k,v代表data.items()],key = lambda x:x ['val'] ,reverse = True)print(sorted_data)  

输出:

  [{'name':'amazon','val':3},{ 'name':'嘿','val':2},{'name':'flipkart','val':1}]  
     
			
        
+20

两个建议的答案都会在每个项目上调用 len()两次。为什么不叫它一次?(不是为了表现,而是为了冷静)

代码

  dicl = {'amazon':[668,667,879],'flipkart ':[678],'嘿':[89,79]} length_dict = {k:len(v)代表k,v代表dicl.items()}#在dict中的长度值上排序,使用长度的倒数为@MrGeek建议sorted_on_values = sorted(length_dict.items(),key = lambda d:-d [1])sorted_dict = dict(sorted_on_values)  

输出 < / p>

  {'amazon':3,'嘿':2,'flipkart':1}  
     
			
        
+20

你可以这样做

  dicl = {'amazon':[668,667,879],'flipkart':[678],'嘿':[89,79 ]} cov_m = {k:len(v)表示k,v表示已排序(dicl.items(),key = lambda x:x [1])}   

输出

  {'amazon':3,'嘿':2,'flipkart':1}  
     
			
        

只有在添加新的键值对时才需要保留顺序,才需要OrderedDict。在OP的情况下,他已经有一个他想要排序的填充字典。 - Sam Legesse 8月29日12:20

@SamLegesse你是对的,这就是为什么我给了两个解决方案。如果他想保留dict,那么可以使用OrderedDict。 - somil 8月29日12:56

或者如果你正在使用python 2 - Laurens Koppenol 8月29日12:56

15
votes
answers
24 views
+10

python字典keyError

python的新手,看起来像是一段简单的可操作代码,产生 KeyError

  patt = list('jkasb')dict = {} for i in patt:dict [i] = 1如果dict [i]为None否则dict [i] +1#此行抛出错误  

错误:KeyError:'j'

沙发
+70
+50

在您的情况下,KeyError正在发生,因为您正在尝试访问不在字典中的键。最初,字典是空的。因此,其中没有密钥存在。

如果您来自C ++背景,这可能看起来很奇怪,因为C ++地图为尚不存在的键提供了默认值。您可以使用 collections.defaultdict 在python中获得相同的行为。修改后的代码如下。我冒昧地将defaultdict转换为代码末尾的常规字典:

  from collections import defaultdict patt ='jkasb'my_default_dict = defaultdict(int)for i in patt:my_default_dict [i] + = 1 my_dict = dict(my_default_dict)#将defaultdict转换为常规字典  

您还可以通过许多其他方式解决此问题。我在下面展示其中一些:

  • 通过检查字典中是否存在密钥:

      patt = 'jkasb'my_dict = {} for pat in patt:my_dict [i] = 1如果我不在my_dict中my_dict [i] +1#检查我是否存在于dict中   < li> 

    使用 dict.get()而没有默认返回值:

      patt ='jkasb'my_dict = {} for我在patt:my_dict [i] = 1如果my_dict.get(i)是None,则my_dict [i] +1#using dict.get print(my_dict)   
  • 使用带有默认返回值的 dict.get()

+50
collections.defaultdict
  from collections import defaultdict d = defaultdict(int)for i in'jkasb':d [i] + = 1   

使用 collections.Counter
  from collections import Counter d = Counter('jkasb')  

避免使用 dict (内置类型)作为变量名。只需迭代'jkasb'而不必将其转换为列表,字符串也是可迭代的。 来自集合导入defaultdict d = defaultdict(int)for i in'jkasb':d [i] + = 1

使用 collections.Counter
  from collections import counter d = Counter('jkasb')  

避免使用 dict (内置类型)作为变量名。只需迭代'jkasb'而不必将其转换为列表,字符串也是可迭代的。 来自集合导入defaultdict d = defaultdict(int)for i in'jkasb':d [i] + = 1

使用 collections.Counter
  from collections import counter d = Counter('jkasb')  

避免使用 dict (内置类型)作为变量名。只需迭代'jkasb'而不必将其转换为列表,字符串也是可迭代的。

+30

由于 dict 最初为空,尝试使用 dict [i] 访问任何值将抛出 KeyError

您应该将其替换为 .get()< / code> 如果未找到密钥则返回 None

  for i in patt:dict [i] = 1 if dict.get( i)是否其他dict [i] + 1   

另一种选择,正如@snakecharmerb所建议的那样,是事先检查你的字典中是否存在密钥: < pre> for pat in patt:dict [i] = 1如果我没有在dict中另外dict [i] + 1

两种解决方案都是等价的,但第二种解决方案可能更“惯用”。

或者也许如果我在dict? - snakecharmerb 2天前

或者简单地说dict [i] = dict.get(i,0)+ 1 - Tomerikoo 2天前

得到它了。Dint知道他们让dict []和dict.get有不同的行为。 - Sachin Verma 2天前

@Tomerikoo谢谢! - Delgan 2天前

0

这些片段: dict [i] dict [i] +1 将尝试从字典中获取一个带有相应键 i的值由于词典中没有任何内容,因此会出现KeyError。

0

您正在尝试访问空字典中的密钥,您也可以使用 defaultdic 所以你不在乎密钥是否已经存在:

  from collections import defaultdict patt = list('jkasb')my_dict = defaultdict(int)for i in patt: my_dict [i] + = 1  
     
			
        
0
votes
answers
41 views
+10

如果正在執行另一個腳本,防止運行python腳本

2

我正在開發一個更大的系統內部有兩個腳本。讓我們打電話給一個foo.py和另一個bar.py如果正在執行另一個腳本,防止運行python腳本

foo創建bar之後將讀取和刪除的文件。現在,如果foo正在運行並正在處理某個文件,bar將在foo完成之前處理同一個文件,從而導致混亂。

foobar由其他內容自動啓動,而不是由運行它們的人手動啓動。 如何確保如果foo正在處理文件,bar無法啓動?

我曾經想過編輯他們都讓foo在開始執行寫入1到一個文本文件和一個當它完成0,並且使bar閱讀文本文件,檢查wheter它可以啓動。但我真的不知道這是最優雅的解決方案,而且我不希望阻止bar如果foo在執行過程中不斷出現故障,剩下的文件在1

+0

難道你不能在子過程中執行foo,並且使用'Popen.poll()'等待foo完成(通過成功或失敗)嗎?另請參閱https://stackoverflow.com/q/43274476/2923755 –

+0

您是否查看了文件鎖定? – 2017-11-11 17:13:30

+0

新手在這裏,沒有關於子進程或文件鎖定的標題。要做我自己的研究,但是,你們能指出任何好的來源嗎? –

沙发
0
1

您可以使用subprocess

在你的主文件:

import subprocess 


def main(): 
    p = subprocess.Popen(['python', 'foo.py']) 
    res = p.wait() 
    if res == 0: 
     print("foo did ok") 
     # execute bar.py 
    else: 
     print("foo failed along the way") 

在foo.py,確保與代碼0退出,如果一切正常: exit(0)(這將返回在主腳本中爲res)。

如果您想在等待foo完成時執行其他操作,也可以使用poll()

def main(): 
    p = subprocess.Popen(['python', 'foo.py']) 

    while not p.poll()==0: 
     print("wait for foo") 
     #do some other magic. but make sure to have a break condition 
     # e.g. if foo takes too long. 
板凳
0
0

的可能的策略:

  • foo build todo.foo
  • 完成後重命名爲todo.bar
  • bar照看todo.bar,計算完成後刪除它。
+0

這與他的「寫1然後0」策略不一樣嗎?如果foo在這裏失敗,bar會被「阻止」,但是沒有看到文件 –

+0

你是對的,你只需要少一個文件來管理。但如果foo失敗,酒吧使用它是個好主意嗎? –

+0

準確地說,我的想法也是大聲笑,但這就是他想要的嘿嘿 –

地板
0
0
import fcntl 

pid_file = 'mysoftware.pid' 
fp = open(pid_file, 'w') 
try: 
    fcntl.lockf(fp, fcntl.LOCK_EX | fcntl.LOCK_NB) 
except IOError: 
    # another instance is running 
    print("already running") 
    sys.exit(1) 

這對我的作品。

0
votes
answers
28 views
+10

函數需要2個參數,但有3個參數?

-1

我對python 3(以及一般編程)非常陌生,而且我在理解爲什麼會發生這種情況時遇到了一些問題。函數需要2個參數,但有3個參數?

class calculator: 

    def addition(x, y): 
     added = x + y 
     print(added) 

    def subtraction(x, y): 
     sub = x - y 
     print(sub) 

    def multiplication(x, y): 
     mult = x * y 
     print(mult) 

    def division(x, y): 
     div = x/y 
     print(div) 

calc = calculator() 

calc.multiplication(3,5) 

,我發現了問題,這個問題:

Traceback (most recent call last): 
File "/Users/JordanM/Desktop/PythonFiles/Calculator.py", line 20, in <module> 
calc.multiplication(3,5) 

TypeError: multiplication() takes exactly 2 arguments (3 given) 

誰能給一些見解,爲什麼這是怎麼回事?有沒有更好的方法來做到這一點?

+0

您需要添加自我所有功能 – Vidya

+1

或每個方法上面的裝飾'@ staticmethod' – PRMoureu

+0

的主要問題是:爲什麼這是一個類? – Matthias

沙发
0
0

您需要將self添加到實例所使用的所有函數中。它在javascript中就像這樣。它指向當前的實例。

def addition(self,x, y): 
     added = x + y 
     print(added) 
+0

非常感謝! –

0
votes
answers
32 views
+10

使用python boto將文件上傳到S3文件夾

0

我試圖從本地目錄上傳文件到S3文件夾。我能夠將文件上傳到S3存儲桶,但我無法將文件上傳到S3存儲桶中的文件夾。使用python boto將文件上傳到S3文件夾

任何人都可以幫忙嗎?我在做什麼錯在這裏..

下面是代碼:

import os 
import sys 
import boto3 
import fnmatch 
import pprint 
import re 
import hashlib 

SOURCE_DIR = '/home/user/Downloads/tracks/' 
BUCKET_NAME = 'mybucket' 
S3_FOLDER = 'mybucket/folder1/' 

client = boto3.client('s3') 

s3 = boto3.resource('s3') 

def get_md5(filename): 
    f = open(filename, 'rb') 
    m = hashlib.md5() 

    while True: 
     data = f.read(10240) 
     if len(data) == 0: 
      break 
     m.update(data) 

    return m.hexdigest() 

def get_etag(filebase,filepath): 
    for item in bucket.objects.all(): 
     keyfile = S3_FOLDER + filebase 
     if(keyfile == item.key): 
      md5 = get_md5(filepath) 
      etag = item.e_tag.strip('"').strip("'") 

      if etag != md5: 
       print(filebase + ": " + md5 + " != " + etag) 
       return(files_to_upload.append(filepath)) 
     else: 
      return(files_to_upload.append(filepath)) 

files_to_upload = [] 
for root, dirnames, filenames in os.walk(SOURCE_DIR): 
    for filename in filenames: 
     filepath = os.path.join(root, filename) 
     get_etag(filename,filepath) 

for f in files_to_upload: 
    client.put_object(Bucket=BUCKET_NAME, Key=f) 
沙发
0
0

文件夾並不真正存在於S3。您可以將文件名稱(對象關鍵字)加上與文件夾路徑類似的東西。

這並不完全清楚,我什麼你的代碼與文件路徑做,但需要你的代碼改成這樣的:

for f in files_to_upload: 
    key = "my/s3/folder/name/" + f 
    client.put_object(Bucket=BUCKET_NAME, Key=key, Body=f) 

注意:您沒有傳遞Body參數,所以我認爲你的代碼只是在S3中創建空對象。

+0

感謝馬克。我現在明白了。有效。我試圖只將修改或新文件上傳到S3。但代碼上傳一切... –

0
votes
answers
23 views
+10

從父類運行Python類的方法,但保留變量

3

我有一個python類和一個父類。從父類運行Python類的方法,但保留變量

class A: 
    def foo(self, num): 
     num1 = num + 3 
     print(num1) 

class B(A): 
    def foo(self, num): 
     super().foo(num) 
     num2 = num1+3 
     print(num2) 

是否有可能使孩子的方法,以保持從父母方法varables,當它調用它super().food(num)在其自己版本的方法以後使用。

或者有沒有更好的方法來追加到您的父母方法的副本?

編輯:我的實際類比這複雜得多。我只是以此爲例。我正在製作一個IRC bot,並且需要一個基礎對象,其他機器人可以基於此對象。 (因此有些方法會在某些機器人中添加部分)

沙发
0
4

在Python中,您在成員函數中分配給的變量不僅僅是繼承樹中該類的局部變量;他們甚至無法用於同一班級的其他方法,或者稍後再次調用該成員函數。換句話說,它們只是普通的局部變量。要分配給對象的成員變量,你必須明確指定對象

class A: 
    def foo(self, num): 
     self.num1 = num + 3 
     print(self.num1) 

class B(A): 
    def foo(self, num): 
     super().foo(num) 
     self.num2 = self.num1+3 
     print(self.num2) 
+0

所以我cound'回報num1'的父母,然後在孩子'NUM1 =超()。食物(NUM)'? –

+0

是的,你可以做到這一點,但這種方法肯定是一個更好的方法。 – Gumboy

板凳
0
1

,如果你想使用父變量時returned.But我會用@Arthur蒟蒻這種方法,這是一個好一點。

class A: 
    def foo(self, num): 
     num1 = num + 3 
     return num1 

class B(A): 
    def foo(self, num): 
     num1 = super().foo(num) 
     num2 = num1+3 
     print(num2) 
G = B().foo(4) 
地板
0
1

我想你想爲此的init函數。最終它取決於你在做什麼。您可能需要一個抽象類或一個承諾在子類中具有某些行爲的接口。這很難說。對於這個問題,這樣的酒吧是所有富的構造,我會做這樣的屬性

class foo: 
    def __init__(self, num1=3): 
    self.num1 =num1 

class bar(foo): 
    def __init__(self, num2 = 3): 
    foo.__init__() 
    self.num2 = self.num1 + num2 
4楼
0
2

您可以定義num1作爲一個實例變量,那麼你就可以在你的B類使用它。

class A(object): 
    def foo(self, num): 
     self.num1 = num + 3 
     print(self.num1) 

class B(A): 
    def foo(self, num): 
     super(B, self).foo(num) 
     num2 = self.num1 + 3 
     print(num2) 

https://docs.python.org/2/tutorial/classes.html#class-and-instance-variables

0
votes
answers
40 views
+10

製作「插入排序」算法更高效 - 的Python 3.5.2

0

我已經嘗試在Python編碼插入排序算法 -製作「插入排序」算法更高效 - 的Python 3.5.2

def insertion(list): 
    checked = 2 
    while (checked <= len(list)): 
     for i in range(checked-1): 
      if list[checked-1] < list[i]: 
       list.insert(i, list[checked-1]) 
       del list[checked] 
     checked+=1 
    return list 

我測量它採取執行1000項排序的時間 - 106.08099999999997第二

1000分之

我發現這是相當緩慢的,因爲 -

def bubbleSort(alist,n): 
    for j in range(1,n): 
     nextnum = alist[j] 
     i = j - 1 
     while i>=0 and alist[i]>nextnum: 
      alist[i + 1] = alist[i] 
      i = i - 1  
     alist[i + 1] = nextnum 

僅僅用了 - 83.71800000000007千分之一一秒

有沒有什麼辦法可以讓我的代碼更有效率/我會不得不使用不同的代碼?如果是這樣,哪種插入排序實現在python中最快?我知道插入排序通常不是最好的算法。這只是爲了我的學校工作,以便我能更好地理解我們學習的算法。

+0

1.您是如何「測量」的?你用'timeit'完成了嗎? 2.如果你想要一個高效的排序算法,不要使用O(n^2)算法:使用合併或快速排序。如果你知道數字的範圍,你可以用基數或桶排序來實現線性時間 – alfasin

+0

我剛用過time.clock()。它可能不準確,但它只是爲了證明它比其他代碼慢。再次,正如我在底部所述,這僅僅是爲了學校工作。我並不是在尋找最高效的算法,但感謝您的建議。 –

沙发
0
1

插入和從列表中刪除比交換位置內容更昂貴。這比冒泡排序更快:

def insertion(M): 
    for i in range(1,len(M)): 
     for j in range(i): 
      if M[i] < M[j]: 
       M[j],M[j+1:i+1] = M[i],M[j:i] 
       break 

注意這裏使用了a,b = b,a「交換」語法,交換的檢查值插入位置,領先交換的剩餘值列表中的一個。而且,一旦交換完成,從內部循環中斷開。無需繼續檢查插入位置。您還可以檢查要交換的值是否已經大於或等於先前排序的值,並且如果爲true,則跳過內部循環:

def insertion(M): 
    for i in range(1,len(M)): 
     if M[i] >= M[i-1]: 
      continue 
     for j in range(i): 
      if M[i] < M[j]: 
       M[j],M[j+1:i+1] = M[i],M[j:i] 
       break 
+0

我看,這非常有幫助,非常感謝你!我想我可以運用這些技術來使我的其他算法更加高效!更新 - 你將時間縮短到原來的40%! –

0
votes
answers
16 views
+10

程序打印輸入python中的年齡較低的值

1

我需要編寫一個程序來獲取人名和年齡,並在名稱STOP已被引入(不包括列表)後打印最年輕人的姓名和年齡程序打印輸入python中的年齡較低的值

我有這到目前爲止,我對如何獲取到較低的值

name = "Joao" 
ageMin = 0 
while name != "STOP": 
    name = input("Digite o nome: ") 
    age = int(input("Digite a sua idade: ")) 
    identity = name, ageMin 
沙发
0
1

您需要正確/不知道做2事情更加爲您code工作:

  • 比較反對年齡最小輸入年齡,到目前爲止,並做適當的事情,如果是年輕(小於)

  • 開始的最低年齡關,就像這樣200因爲沒有人會比年輕0所以這不會有任何效果,因爲它代表

所以這裏工作得很好:

name = "Joao" 
ageMin = 200 
nameMin = name 
while name != "STOP": 
    name = input("Digite o nome: ") 
    age = int(input("Digite a sua idade: ")) 
    if age < ageMin: 
     ageMin = age 
     nameMin = name 

print("youngest:", nameMin, "at age", ageMin) 
+0

請'上vote'太表示您的讚賞!謝謝 **:)** –

0
votes
answers
27 views
+10

查找特定索引?

0

如果我有兩個字符串,如何找到字符串停止匹配的索引? 'abcdefghijk'和錯誤的字母表'abcdxyz',我知道他們停止匹配在索引4,但我怎樣才能在功能設置中輸出?查找特定索引?

+0

也許你可以在循環使用find()方法,並打破時,它不符合你的字符串? –

沙发
0
0

使用enumerate()函數查找索引,對於這第二個字符串在信中並沒有第一個字符串中匹配當前信 -

def matcher(str1, str2): 
    for idx, item in enumerate(str1): 
    if item != str2[idx]: 
     return idx 
    return -1 # if no differing letter in second string 

print(matcher('abcdefghijk', 'abcdxyz')) # 4 
板凳
0
0

使用簡單的一些comparisonsslicedstrings

,直到它到達第一string結束並對它們進行比較,我們可以創建一個簡單的function,保持slicingstrings

def match(s1, s2): 
    for i in range(len(s1)+1): 
     if s1[:i] != s2[:i]: 
      return i - 1 
    return -1 

和一些測試:

>>> match('abcdefghijk', 'abcdxyz') 
4 
>>> match('124', '123') 
2 
>>> match('123456', '123abc') 
3 
>>> match("abcdef", "abcdef") 
-1 
0
votes
answers
22 views
+10

python3/syslog:多個系統日誌流?

0

我的python3程序有一些子模塊,我希望它們每個發送帶有不同系統日誌值的系統日誌消息。例如,其中一個可能會發送到myprogram/submod0,另一個可能會發送到myprogram/submod1。我使用syslog-ng將這些消息路由到不同的日誌文件。python3/syslog:多個系統日誌流?

我希望做的是這樣的事情,這是我所知道的是目前不可能在我這裏寫的方式:

syslog0 = syslog.openlog('myprogram/submod0', 
         syslog.LOG_PID, syslog.LOG_MAIL) 
syslog1 = syslog.openlog('myprogram/submod1', 
         syslog.LOG_PID, syslog.LOG_MAIL) 

...然後,內submod0,我想送系統日誌消息是這樣的...

syslog0.syslog('some sort of message') 

...並在submod1這樣...

syslog1.syslog('another message') 

但是,當然syslog.openlog不會返回任何類型的對象,我可以用這種方式作爲句柄。

有沒有什麼方法可以用python3的syslog工具完成我想要的功能?

我想我可以爲我想發送的每個系統日誌消息發出一個新的openlog。例如...

def mysyslog(ident, message): 
    syslog.openlog('myprogram/{}'.format(ident), 
        syslog.LOG_PID, syslog.LOG_MAIL) 
    syslog.syslog(message) 

...然後用我的submod0mysyslog('submod1', message)mysyslog('submod0', message)submod1內。這是我能完成自己想做什麼的唯一方式嗎?

預先感謝您。

沙发
0
0

我找不到任何現有的python模塊做我想做的事,所以我決定編寫自己的syslog包裝器。它被寫爲打開基於host:port或套接字文件(如/dev/log)的系統日誌連接,然後接受所有其他參數,如facility,severity,program等,以在每次調用時發送系統日誌消息。

在所有參數處於各個日誌記錄方法調用級別時,可以將此類打包到更高級別,以便通過program提供句柄,例如,通過我在原始問題中指定的唯一連接這裏。

我只用python3.6和/dev/log的情況下測試了下面的代碼。它適用於我,但使用它需要您自擔風險。

#!/usr/bin/python3.6 

import os 
import sys 
import socket 
import datetime 

# Only imported for the syslog.LOG_INFO and syslog.LOG_USER constants. 
import syslog 

# Appends a newline in all cases. 
def _log_stderr(message): 
    if message: 
     sys.stderr.write(message) 
    sys.stderr.write('
') 
    sys.stderr.flush() 

# XSyslog: a syslog wrapper class. 
# 
# This module allows the facility (such as LOG_USER), the 
# severity (such as LOG_INFO), and other syslog parameters 
# to be set on a message-by-message basis via one, single 
# syslog connection. 
# 
# Usage: 
# 
# slog = XSyslog([server=server], [port=port], [proto=proto], 
#     [clientname=clientname], [maxlen=maxlen]) 
# 
# This allows three cases: 
# (1) Connect to syslog via UDP to a host and port: 
#  Specify host, port, and proto='UDP'. 
# (2) Connect to syslog via TCP to a host and port: 
#  Specify host, port, and proto='TCP'. 
# (3) Connect to syslog via a socket file such as /dev/log. 
#  Specify proto=filename (e.g., proto='/dev/log'). 
#  In this case, host and port are ignored. 
# 
# clientname is an optional field for the syslog message. 
# maxlen is the maximum message length. 
# 
# Once the XSyslog object is created, the message can be sent as follows: 
# 
# slog = XSyslog([... parameters ...]) 
# slog.log(message, [facility=facility], [severity=severity], 
#      [timestamp=timestamp], [hostame=hostname], 
#      [program=program], [pid=pid]) 
#  facility defaults to LOG_USER 
#  severity defaults to LOG_INFO 
#  timestamp defaults to now 
#  hostname if None, use clientname if it exists; if '', no hostname. 
#  program defaults to "logger" 
#  pid  defaults to os.getpid() 

class XSyslog(object): 

    def __init__(self, server=None, port=None, proto='udp', clientname=None, maxlen=1024): 
     self.server  = server 
     self.port   = port 
     self.proto  = socket.SOCK_DGRAM 
     self.clientname = None 
     self.maxlen  = maxlen 
     self._protoname = '' 
     self._socket  = None 
     self._sockfile = None 
     self._connectargs =() 
     self._me   = os.path.splitext(self.__class__.__name__)[1][1:] 

     if proto: 
      if proto.lower() == 'udp': 
       self._protoname = proto.lower() 
       self.proto  = socket.SOCK_DGRAM 
       self._socketargs = (self.server, self.port, socket.AF_UNSPEC, self.proto) 
      elif proto.lower() == 'tcp': 
       self._protoname = proto.lower() 
       self.proto  = socket.SOCK_STREAM 
       self._socketargs = (self.server, self.port, socket.AF_UNSPEC, self.proto) 
      elif len(proto) > 0: 
       self._sockfile = proto 
       self._protoname = self._sockfile 
       self.proto  = socket.SOCK_DGRAM 
       self._socketargs = (socket.AF_UNIX, self.proto) 

     badargs = False 
     if self._sockfile: 
      pass 
     elif self.server and self.port: 
      pass 
     else: 
      badargs = True 
     if not self.proto: 
      badargs = True 
     if badargs: 
      raise ValueError("'proto' must be 'udp' or 'tcp' with 'server' and 'port', or else a socket filename like '/dev/log'") 

     if not self.clientname: 
      try: 
       self.clientname = socket.getfqdn() 
       if not self.clientname: 
        self.clientname = socket.gethostname() 
      except: 
       self.clientname = None 

    def _connect(self): 
     if self._socket is None: 
      if self._sockfile: 
       self._socket = socket.socket(*self._socketargs) 
       if not self._socket: 
        _log_stderr(':::::::: {}: unable to open socket file {}'.format(self._me, self._sockfile)) 
        return False 
       try: 
        self._socket.connect(self._sockfile) 
        return True 
       except socket.timeout as e: 
        _log_stderr(':::::::: {}: sockfile timeout e={}'.format(self._me, e)) 
        # Force-close the socket and its contained fd, to avoid fd leaks. 
        self.close() 
       except socket.error as e: 
        _log_stderr(':::::::: {}: sockfile error f={}, e={}'.format(self._me, self._sockfile, e)) 
        # Force-close the socket and its contained fd, to avoid fd leaks. 
        self.close() 
       except Exception as e: 
        # Any other exception which might occur ... 
        _log_stderr(':::::::: {}: sockfile exception f={}, e={}'.format(self._me, self._sockfile, e)) 
        # Force-close the socket and its contained fd, to avoid fd leaks. 
        self.close() 
       return False 
      else: 
       addrinfo = socket.getaddrinfo(*self._socketargs) 
       if addrinfo is None: 
        return False 
       # Check each socket family member until we find one we can connect to. 
       for (addr_fam, sock_kind, proto, ca_name, sock_addr) in addrinfo: 
        self._socket = socket.socket(addr_fam, self.proto) 
        if not self._socket: 
         _log_stderr(':::::::: {}: unable to get a {} socket'.format(self._me, self._protoname)) 
         return False 
        try: 
         self._socket.connect(sock_addr) 
         return True 
        except socket.timeout as e: 
         _log_stderr(':::::::: {}: {} timeout e={}'.format(self.me, self._protoname, e)) 
         # Force-close the socket and its contained fd, to avoid fd leaks. 
         self.close() 
         continue 
        except socket.error as e: 
         _log_stderr(':::::::: {}: {} error e={}'.format(self._me, self._protoname, e)) 
         # Force-close the socket and its contained fd, to avoid fd leaks. 
         self.close() 
         continue 
        except Exception as e: 
         # Any other exception which might occur ... 
         _log_stderr(':::::::: {}: {} exception e={}'.format(self._me, self._protoname, e)) 
         # Force-close the socket and its contained fd, to avoid fd leaks. 
         self.close() 
         continue 
       # Force-close the socket and its contained fd, to avoid fd leaks. 
       self.close() 
       return False 
     else: 
      return True 

    def close(self): 
     try: 
      self._socket.close() 
     except: 
      pass 
     self._socket = None 

    def log(self, message, facility=None, severity=None, timestamp=None, hostname=None, program=None, pid=None): 

     if message is None: 
      return 

     if not facility: 
      facility = syslog.LOG_USER 

     if not severity: 
      severity = syslog.LOG_INFO 

     pri = facility + severity 

     data = '<{}>'.format(pri) 

     if timestamp: 
      t = timestamp 
     else: 
      t = datetime.datetime.now() 
     data = '{}{}'.format(data, t.strftime('%Y-%m-%dT%H:%M:%S.%f')) 

     if hostname is None: 
      if self.clientname: 
       data = '{} {}'.format(data, self.clientname) 
     elif not hostname: 
      # For hostname == '', leave out the hostname, altogether. 
      pass 
     else: 
      data = '{} {}'.format(data, hostname) 

     if program: 
      data = '{} {}'.format(data, program) 
     else: 
      data = '{} logger'.format(data) 

     if not pid: 
      pid = os.getpid() 

     data = '{}[{}]: {}'.format(data, pid, message).encode('ascii', 'ignore') 

     if not self._socket: 
      self._connect() 

     if not self._socket: 
      raise Exception('{}: unable to connect to {} syslog via {}'.format(self._me, self._protoname, self._socketargs)) 
     try: 
      if self.maxlen: 
       self._socket.sendall(data[:self.maxlen]) 
      else: 
       self._socket.sendall(data) 
     except IOError as e: 
      _log_stderr(':::::::: {}: {} syslog io error {} via {}'.format(self._me, self._protoname, e, self._socketargs)) 
      self.close() 
      raise 
     except Exception as e: 
      # Any other exception which might occur ... 
      _log_stderr(':::::::: {}: {} syslog exception {} via {}'.format(self._me, self._protoname, e, self._socketargs)) 
      self.close() 
      raise 
板凳
0
0

好的。我看到,我可以通過??做到這一點...

https://docs.python.org/3/library/logging.handlers.html#sysloghandler

這是一個回答我的問題,但它是不理想的,因爲我想避免使用logging模塊,如果在所有可能。

我將繼續尋找另一種方式來做到這一點。